Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Lagomに学ぶマイクロサービス / Learn Microservice with Lagom
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
yuiwai
August 27, 2021
Programming
890
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Lagomに学ぶマイクロサービス / Learn Microservice with Lagom
yuiwai
August 27, 2021
More Decks by yuiwai
See All by yuiwai
scalajs-reactで作るフロントエンド / Frontend With scalajs-react
yuiwai
3
620
Scalaで作るカジュアルゲーム
yuiwai
1
590
Other Decks in Programming
See All in Programming
Webの地図
yosuke_furukawa
PRO
6
4.2k
週末にAI-DLCを本気で回したら$1,600溶けた
hbashimizu
0
130
AIは賢い。でも実行環境は? CLIおじさんがAI時代に伝えたいこと ~ CLIおじさんがAI時代に伝えたいこと ~
curekoshimizu
1
240
業務時間外もAIに働いてもらう話
colorful12
3
10k
市販E-Readerを乗っ取れ 〜Embedded Swiftで電子ペーパーガジェットを制御する〜
trickart
0
170
モバイル交通系ICへのチャージ実例から考える、クロスプラットフォーム開発におけるiOS実機テスト設計とCI運用
yusuga
1
350
Claude Codeを組織的に動かして月400PRを実現した話
happy_ryo
0
270
LL言語やWebフレームワークのPostgreSQL対応 〜DBの機能がユーザーに届くまで〜
kentaroutakeda
0
150
マイコン向けの軽量Ruby「PicoRuby」で各種デバイスを制御するネイティブアプリの実現手法
bash0c7
0
340
iOS開発×AI駆動開発 〜最近使って便利だったスキルの話〜
nogu66
0
140
AI に Inclusive UI を書かせよう — Design Rules Skill で Compose UI を作り直す
theoriatec2024
1
470
AI Agent時代のリアーキテクチャ戦略と実践
hokaccha
9
3.9k
Featured
See All Featured
Learning to Love Humans: Emotional Interface Design
aarron
275
41k
How To Speak Unicorn (iThemes Webinar)
marktimemedia
1
570
WCS-LA-2024
lcolladotor
0
830
Docker and Python
trallard
47
4.2k
Facilitating Awesome Meetings
lara
57
7.1k
エンジニアに許された特別な時間の終わり
watany
108
250k
WENDY [Excerpt]
tessaabrams
13
39k
Navigating Weather and Climate Data
rabernat
0
510
Jess Joyce - The Pitfalls of Following Frameworks
techseoconnect
PRO
1
410
Evolving SEO for Evolving Search Engines
ryanjones
0
280
YesSQL, Process and Tooling at Scale
rocio
174
15k
Getting science done with accelerated Python computing platforms
jacobtomlinson
2
480
Transcript
Lagomに学ぶマイクロサービス 2021.8.13 - Yuichiro Iwai
本日の内容 マイクロサービスフレームワークであるLagomの 主要なコンセプトを見つつ、マイクロサービスを 作る上でどんなことに考慮が必要か(の一部)を 学びます。
Lagomとは? • Lightbend社が作ったマイクロサービスフレームワーク https://www.lagomframework.com/ • Java/Scalaをサポート • Akka/Playをベースに構築されている
LagomのServiceの構成 Service インターフェース 具象実装 API定義 ・・・・・ API実装 ひとつのServiceは定義(インターフェース)と実装の2つの(sbt上の)プロジェクトから構成される
LagomのServiceの構成 Service インターフェース 具象実装 API定義 ・・・・・ API実装 こうすることで、他のサービスは実装の詳細を知る必要がなくなり、インターフェースだけに依存してその サービスを呼び出すことが出来る Other
Service
LagomのEntity永続化(イベントソーシング) Service Entity 永続化層(Journal) (Cassandra, RDB, ...etc) Client Request Command
Reply Response State Event 永続化層(Snapshot) (Cassandra, RDB, ...etc) イベントソーシングの全体像。個々の処理を順に見ていく
LagomのEntity永続化(イベントソーシング) Service ClientからServiceへリクエストが送信される Entity 永続化層(Journal) (Cassandra, RDB, ...etc) Client Request
Command Reply Response State Event 永続化層(Snapshot) (Cassandra, RDB, ...etc) RegisterUserRequest( Name: “Yuichiro” )
LagomのEntity永続化(イベントソーシング) Service ServiceはEntity呼び出しの時点でEntityの識別子を必要とする(新規登録の場合は新しい識別子を発行 する場合もある) Commandはその識別子で識別される Entityへ送られる。 Entity 永続化層(Journal) (Cassandra, RDB,
...etc) Client Request Command Reply Response State Event 永続化層(Snapshot) (Cassandra, RDB, ...etc) RegisterUserRequest( Name: “Yuichiro” ) RegisterUserCommand( Name: “Yuichiro” ) 識別子発行
LagomのEntity永続化(イベントソーシング) Service Entity 永続化層(Journal) (Cassandra, RDB, ...etc) Client Request Command
Reply Response State Event 永続化層(Snapshot) (Cassandra, RDB, ...etc) RegisterUserRequest( Name: “Yuichiro” ) RegisterUserCommand( Name: “Yuichiro” ) UserRegistered( Name: “Yuichiro” ) State.User.Name = event.Name 識別子発行 EntityはCommandを受け取り、Eventを発行する。Eventの保存が成功したら、それを Stateに反映すること で状態を更新する。
LagomのEntity永続化(イベントソーシング) Service Entity 永続化層(Journal) (Cassandra, RDB, ...etc) Client Request Command
Reply Response State Event 永続化層(Snapshot) (Cassandra, RDB, ...etc) RegisterUserRequest( Name: “Yuichiro” ) RegisterUserCommand( Name: “Yuichiro” ) UserRegistered( Name: “Yuichiro” ) State.User.Name = event.Name 識別子発行 ServiceはEntityからの返答を非同期に受け取り、 Clientへレスポンスを返す。 上記の例では発行した識別子だけを返している。 Done 識別子
LagomのEntity配置戦略(Cluster Sharding) Service EntityはEntityID(Entityの識別子)によってService内で一意に特定され、どのシャードに配置されるかが決 まる。 Node Request Response Node Shard
Shard Shard Shard Shard Shard Entity Entity Entity Entity Entity Entity Entity Entity Entity Entity Entity Entity API実装 (EntityIDから Shardを特定) 注)Cluster ShardingはSplit Brain問題の影響をモロに受けるが、それはまた別の機会に
LagomのEntity配置戦略(Cluster Sharding) Service EntityはEntityID(Entityの識別子)によってService内で一意に特定され、どのシャードに配置されるかが決 まる。 Node Request Response Node Shard
Shard Shard Shard Shard Shard Entity Entity Entity Entity Entity Entity Entity Entity Entity Entity Entity Entity API実装 (EntityIDから Shardを特定) 注)Cluster ShardingはSplit Brain問題の影響をモロに受けるが、それはまた別の機会に 図を見ると分かる通り、 Serviceはクラスタ(複数のノードか ら形成されている)である。 つまり、Serviceは単体でスケールイン /アウトする。 この点は非常に重要。
LagomのCQRS戦略(Read-side) Journalに流れてくるイベント (EventStream)を順に処理して読み取り側のモデルを保存する。 Read-sideの更新には若干のタイムラグがあり、結果整合性であることに注意。 永続化層(Journal) (Cassandra, RDB, ...etc) 永続化層(Read-side) (Cassandra,
RDB, ...etc) EventProcessor (Read Model Updater) 永続化されたイベントを 順に取得 読み取り用のモデルを 構築し保存 Write Read
LagomのCQRS戦略(Read-side) 永続化層(Journal) (Cassandra, RDB, ...etc) 永続化層(Read-side) (Cassandra, RDB, ...etc) EventProcessor
(Read Model Updater) 永続化されたイベントを 順に取得 読み取り用のモデルを 構築し保存 Write Read ユーザ登録イベントに対して、 SQLを利用してRead-sideを更新する例
LagomのCQRS戦略(Read-side) 永続化層(Journal) (Cassandra, RDB, ...etc) 永続化層(Read-side) (Cassandra, RDB, ...etc) EventProcessor
(Read Model Updater) 永続化されたイベントを 順に取得 読み取り用のモデルを 構築し保存 Write Read UserRegistered ( Name: “Yuichiro” ) ユーザ登録イベントに対して、 SQLを利用してRead-sideを更新する例 イベントをJournalから読み取る。どこまで読み取ったかの offsetを保持しているので、 Journalのデータが破 損しない限り、いつかは追い付く。
LagomのCQRS戦略(Read-side) 永続化層(Journal) (Cassandra, RDB, ...etc) 永続化層(Read-side) (Cassandra, RDB, ...etc) EventProcessor
(Read Model Updater) 永続化されたイベントを 順に取得 読み取り用のモデルを 構築し保存 Write Read UserRegistered ( Name: “Yuichiro” ) INSERT INTO user (name) VALUES (‘Yuichiro’) ユーザ登録イベントに対して、 SQLを利用してRead-sideを更新する例 Read-side(読取専用:CQRSでいうところのQuery側に利用する永続化層へとイベントを同期する)。上記 の例ではSQLを利用してRDBに保持している想定。
LagomのCQRS戦略(Read-side) Read-sideの構築は単純なCRUD操作になる。泥臭い書き方が求められる反面、どんな永続化層を選ぶ ことも出来る自由度があるので、データ構造に合わせてより良いものを選択すればいい。 永続化層(Journal) (Cassandra, RDB, ...etc) 永続化層(Read-side) (Cassandra, RDB,
...etc) EventProcessor (Read Model Updater) 永続化されたイベントを 順に取得 読み取り用のモデルを 構築し保存 Write Read UserRegistered ( Name: “Yuichiro” ) INSERT INTO user (name) VALUES (‘Yuichiro’) ユーザ登録イベントに対して、 SQLを利用してRead-sideを更新する例
サービスの結合 Service AからService BのAPIをリクエストしてそのレスポンスを受け取り、自身のレスポンスを生成する。 処理は同期的であり、シンプル。 Service A Service B Request
Request ▪ 同期的なアプローチ Response Response
サービスの結合 Service A Service B Request Request ▪ 同期的なアプローチの問題点 Response
Response もし、Service Bがレスポンスを返さなかったら? Error?
サービスの結合 • Service Aはタイムアウトまで、待たされる(ブロックされる)かもしれない = パフォーマンスの劣化、障害の伝播 • Service Aは処理を「失敗」と判断してエラーを返すが、実は Service
Bの処理は成功しているかもし れない = データ不整合 Service A Service B Request Request ▪ 同期的なアプローチの問題点 Response Response もし、Service Bがレスポンスを返さなかったら? Error?
サービスの結合 Service A Service B Request Request ▪ 同期的なアプローチの問題点 Response
Response もし、Service Bがレスポンスを返さなかったら? Error? - Service Aはタイムアウトまで、待たされる(ブロックされる)かもしれない = パフォーマンスの劣化、障害の伝播 - Service Aは処理を「失敗」と判断してエラーを返すが、実は Service Bの処理は成功しているかもし れない = データ不整合 【教訓】分散処理において、整合性を担保するのは非常に難しい
メッセージブローカーによるサービスの協調 ServiceからはイベントをTopicとしてMessage Brokerへpublishする。 他のServiceはTopicをsubscribeすることによって、関心のあるイベントを待ち受ける。 Service A Service B Request ▪
間にメッセージブローカーを挟んだアプローチ Response Message Broker (Kafkaなど) Topic A Topic A Topic B Topic B
メッセージブローカーによるサービスの協調 TopicはJournalに保存されたイベントに基づいて発行される(つまり、ロストしない) 読み取りはPULL型であり、Topicの発行側はその利用者について気にする必要がない。 Service A Service B Request ▪ 間にメッセージブローカーを挟んだアプローチ
Response Message Broker (Kafkaなど) Topic A Topic A Topic B Topic B Journal Journal
メッセージブローカーによるサービスの協調 注意すべきは、Topicでのイベントの受け渡しは非同期であり、結果整合性であるということ。 つまり、いつかは収束するけど、それがいつかは分からない。 Service A Service B Request ▪ 間にメッセージブローカーを挟んだアプローチ
Response Message Broker (Kafkaなど) Topic A Topic A Topic B Topic B 非同期処理
メッセージブローカーによるサービスの拡張 Core Service データ分析 ▪ Topicを通じて様々な外部拡張をおこなうことが出来る 外部サービス Topic Topic バックアップ
Topic 検証環境 Topic 拡張が期待されるユースケースにぴったり! 内部サービス Topic
Circuit Breaker ▪ Serviceは常にすべてがHealthyとは限らない Service A Service B Request Request
Response Response 先ほど見た、同期的な呼び出しが失敗した例。 Service Bが連携先の外部サービスであったとして、そこで何か障害が発生してい る、という状況が考えられる。 (Service AはService Bのクライアントである) 障害発生中
Circuit Breaker ▪ Serviceは常にすべてがHealthyとは限らない Service A Service B Request Request
Response Response 先ほど見た、同期的な呼び出しが失敗した例。 Service Bが連携先の外部サービスであったとして、そこで何か障害が発生してい る、という状況が考えられる。 (Service AはService Bのクライアントである) 障害発生中 この状況下で、Service Bへのリクエストを投げ 続けるのは得策ではない。 (リクエストがより詰まり続けるだけ) 遅延はService Aのクライアントにも伝播してし まう。
Circuit Breaker ▪ Serviceは常にすべてがHealthyとは限らない Service A Service B Request Response
Service Bの状態を「接続不能」と見なして、早期に失敗させる。 こうすることで、Service Bに余計な負荷を掛けず、復旧を待つと同時に、 Service A 自体の応答速度を保つことで、障害の伝播を食い止める。 障害発生中 Fail-Fast
Circuit Breakerの状態遷移 ▪ Circuit Breakerは段階的に状態遷移をしながら復旧を待つ https://www.lagomframework.com/documentation/1.4.x/scala/ServiceClients.html#Circuit-Breakers から拝借 Closed: 正常な状態。障害検知時に Openに遷移する。
Open: 全てのリクエストを早期失敗させる。一定時間経過で Half-Openへ遷移する。 Half-Open: 最初の1リクエストだけを接続する。 => 成功したら、Closedへ遷移する。 => 失敗したら、Openへ遷移する。
まとめ • Lagomはサクっと試せるマイクロサービスフレームワーク • 設計思想や技術スタックには学ぶべき点がたくさんある • 特に、非同期分散システムをどう構築すべきか、という点に おいては非常に勉強になる技術の宝庫 • 現実問題として、実装/運用はそんなに簡単ではない
• 部分的に結合可能なのもマイクロサービスの利点 • 既存システムの一部として置くのもよい
ご清聴ありがとうございました