ブログ記事
「なんとなく分散」を超えるために──『マイクロサービスパターン』が整理するサーガ・CQRS・契約テスト
マイクロサービスへの移行を決断するのは比較的簡単だ。難しいのは、データベースを分割した後にどうトランザクションを管理するか、複数サービスにまたがる検索をどう処理するか、自動テストをどう設計するかという「その後」の問いだ。
Chris Richardson の『マイクロサービスパターン 実践的システムデザインのためのコード解説』(インプレス、2020年)は、フードデリバリーサービス「FTGO」を題材に、Java・Spring Boot・Eventuate Tram を使った動作するコードを通じて、こうした問いへの具体的な回答を示す。コードは Java スタックに依存しているが、設計の考え方は言語を問わず参照できる。
1. サービスをどこで切るか──「ビジネス境界」による分割基準
マイクロサービスへの移行でよくある失敗が、テーブル単位や技術レイヤー単位でサービスを切ってしまう「分散モノリス」だ。これでは開発効率が上がらないどころか、デプロイ依存関係が増えて状況が悪化する。
本書はサービス分割の基準として、ドメイン駆動設計(DDD)の「サブドメイン」と「境界づけられたコンテキスト」を採用する。ビジネス能力ごとに境界を引き、各サービスが独立してデプロイできる状態を目指す設計だ。分割後も依存関係が残る場合は「分散モノリス」のアンチパターンに陥っているサインとして、本書はトレードオフを整理する。
正確に境界を引くことは一度の設計では難しい。本書はドメインの理解が深まるにつれて分割を見直す反復的なアプローチを前提としており、既存モノリスから段階的にサービスを切り出す「Strangler Application パターン」も解説している。
2. 分散環境で整合性をどう保つか──サーガパターンの設計
サービスごとにデータベースを持つ構成では、従来の 2 フェーズコミット(XA)は可用性の低下を招くため推奨されない。本書が代替として提示するのが「サーガ(Saga)パターン」だ。
サーガは、それぞれのサービスがローカルトランザクションを実行し、その完了をイベントやメッセージで次のサービスに通知することで処理の連鎖を作る。途中でエラーが発生した場合は、それまでに完了したトランザクションを逆順に打ち消す「補償トランザクション」を実行して整合性を取り戻す。
サーガの実装方式には 2 種類ある。各サービスがイベントを介して自律的に処理を進める「コレオグラフィ」と、オーケストレーターが全体の処理フローを管理する「オーケストレーション」だ。本書はどちらの方式も FTGO のコードで実装し、並行処理時の不整合(サーガが ACID トランザクションの「分離性」を保証しない点)への対処方法も含めて詳細に論じる。
3. 横断クエリをどう捌くか──CQRS とイベントソーシングの連携
データベースを分割すると、複数サービスにまたがる JOIN クエリが使えなくなる。注文情報と顧客情報を一覧表示するような処理が、書き込み系のサービス間 API 呼び出しの連鎖になってしまうケースが典型例だ。
本書が提示する解決策が「CQRS(コマンドクエリ責任分離)」だ。書き込み(コマンド)と読み取り(クエリ)のモデルを完全に分離し、読み取り専用のビューを非同期で構築する。イベントソーシングと組み合わせることで、アプリケーションのあらゆる状態変化をイベントとして保存し、そのイベントから任意の読み取りビューを再構築できる構成を実現する。
この設計は導入コストが高い。しかし、読み取りの高速化と書き込みの独立性を両立できるため、スケーラビリティと検索パフォーマンスが問題になるシステムでは選択肢になる。本書は CQRS の複雑さを正直に認めつつ、どのような条件で採用を判断するかを論じる。
DevBookPath のマップで確認する
この本の学習パス上の位置づけ・前後の読書順は、DevBookPath のグラフで辿れます。
本記事のリンクには Amazon アソシエイト等の広告が含まれる場合があります。リンク経由の購入で運営者に紹介料が支払われることがあります。
この記事を共有
この地図を共有