なぜマイクロサービスは失敗するのか?
Eberhard Wolffさんのこのプレゼンの要約です
https://www.youtube.com/watch?v=B3O-qYM-Kkw
共通のデータモデル
共通のデータモデルを通信に使う
各サービスで必要となるデータの内部モデルは異なるかもしれない
データモデルが、共通ライブラリと同じ意味合いになる
すべてのサービスが、最新のライブラリを使わなくてはならない
共通データモデルの変更は、すべてのサービスのデプロイを伴う
https://gyazo.com/938f9dae920773a72886e03c1e17766c
(Kafkaのようなストレージに格納された)イベントを共有するのも同じ
本質的には共有データベーススキーマと変わらない。
イベントデータモデルを変更するのが難しくなる
モデルから1属性を削除するのは特に困難だ
なので、モデルは太り続けることになる
https://gyazo.com/7c8fc7525a6e183fcd0ca25efe2613fe
処方箋
マイクロサービスに閉じたローカルデータモデルを使う
通信にグローバルなデータモデルを使わない
そうするとシステム全体でのデータモデルの数は増える。
これは独立性と共有データモデルのトレードオフである
https://gyazo.com/ce75ca6c2ce6776e7ff65b87f06b4125
フレイキーシステム
障害が起きる可能性のあるポイントがたくさんある
数多くのサーバ
数多くのネットワーク経路
数多くのサービス
1つのコンポーネントの障害が、別のサービス群にに波及していく
https://gyazo.com/8b44936af6b9c2bfd9a62eddd285dc7b
処方箋
レジリエンスにしよう
別のマイクロサービスに障害が発生しても、他のサービスは動き続けられるように設計する
ソリューションは、Release It! 参照
デグラレーションを用意する
与信が障害発生中で注文を全部受け付けられなくても、ある上限額までは受け付ける、とか
すくなくとも意味のわかるエラーを返すようにする
決して呼び出し側を永遠に待たせるようなことがあってはならない
レジリエンスにも限界がある
セキュリティサービスに障害が起きたら…?
同期呼び出し
同期呼び出しは、多段になっても理解しやすいが…
ネットワークトラフィックによる性能問題やレイテンシの増加につながる。
処方箋
非同期にしよう
ビジネスイベントだったら非同期は自然なことだ。
ドメインの独立な部分は、他とのサービスとのやりとりが発生しないことを意味するから。
エンティティサービス
ドメインオブジェクトの1つ1つをマイクロサービスとすること
マスタ的なエンティティのマイクロサービスにアクセス集中することになる
性能劣化やレイテンシの増加につながる
レジリエンスの観点からも、障害が波及しやすい構成になる
代わりに1つのデータベースを、複数のマイクロサービスから覗きにいく方式が考えられる
性能、レイテンシの問題は解消される
が、共通データモデルやレジリエンスの問題は解消できない
https://gyazo.com/d9d508c149dcac7af8acac95eecf5f9c
処方箋
マイクロサービスは閉じた固有のデータモデルをそれぞれで持つように設計する。
最悪、データベースを共有したとしても、スキーマはサービス毎に分けてる
https://gyazo.com/4072c92ceee66ff9389d7d1b0aabe88d
悪い構造
「システムは柔軟でメンテナンスしやすいだろう。なぜならマイクロサービスアーキテクチャだからね」
複雑な依存関係そのままに、モノリスをマイクロサービス化しても、構造的には何も変わらない。
マイクロサービスは、モジュールの別の一表現に過ぎない
マイクロサービスだけでは、高い結合性や低い凝集性を改善できない
泥団子をマイクロサービス化しても、ちょっと小さな泥団子がたくさんできるだけだ
処方箋
ロジックの結合度を下げる
Bounded Contextを設計する: 1マイクロサービスで完結したドメインモデルになるように
サービス間のやりとりを減らす
Bounded Contextごとにマイクロサービスに移行する
既存の構造をそのまま使わないように!
アーキテクチャ構造を修正したければ、マイクロサービスはその助けにはならない。
アーキテクチャ構造を修正したければ、そのアーキテクチャ構造を修正しよう。