インラインコード
これは、マイクロサービスアーキテクチャや分散システムにおいて最も悩ましい問題の一つ、「論理的な境界」と「物理的な境界」の不一致、そして「同期通信による隠れた結合」に関する非常に鋭い質問です。
アプリケーションコード(ドメイン層やユースケース層)が独立していても、インフラ層がデータベースや外部APIコールを通じて同期的に強く結びついている場合、それは「分散モノリス」と呼ばれる状態になりがちです。この状態は、モノリスの複雑さと分散システムの不安定さという両方の欠点を併せ持つため、適切な分離の判断が不可欠です。
ご要望の構成に従い、この意思決定と検証のプロセスを詳細に解説します。
前提:ここでの「共有された物理的なシステム基盤」の定義
議論を明確にするため、ここで言う「基盤の共有」とは以下のような状態を指すこととします。
共有データベースインスタンス
論理的にはスキーマが分かれているが、物理的に同じRDSインスタンスやDBクラスタ上に同居している(リソース競合、「うるさい隣人」問題)。
共有コンピュートクラスタ
同じKubernetesクラスタ上で、異なるNamespaceで動いている(ノード障害の影響範囲、クラスタ全体のアップグレード時の影響)。
同期的なネットワーク経路
異なるサービスだが、業務遂行のために常にREST/gRPCで同期的に呼び出し合っており、ネットワーク遅延や相手のダウンが即座に自分に波及する状態。
ステップ1:現状分析と仮説構築(意思決定フェーズ)
まず、現状のシステムがどのように振る舞っているかを定量的なデータに基づいて分析し、「インフラを分離すべきか否か」の仮説を立てます。
1. メカニズム:同期通信とリソース競合の可視化
「コード上の独立性」に騙されず、「実行時の依存性」を暴き出します。
分散トレーシング(Jaeger, Datadog, AWS X-Rayなど)
・分析対象
1つのユーザーリクエストが、いくつのサービスを同期的に連鎖して呼び出しているか(トレースの深さと広さ)。
・着目点
「サービスAの処理時間の80%が、サービスBからの応答待ちである」というような状態。
これは強い動的結合を示します。
インフラストラクチャメトリクス
・分析対象
CPU、メモリ、I/O、データベース接続数、DBロック待機時間。
・着目点
「サービスAが負荷ピークを迎えると、サービスBのDBクエリのレイテンシが悪化する」という相関関係。これは物理リソースを共有していることによる「うるさい隣人」効果です。
アプリケーションログとエラーレート
・分析対象
タイムアウトエラー、接続拒否エラー。
・着目点
「サービスBがダウンした瞬間、サービスAでタイムアウトエラーが多発し、機能不全に陥る」現象。これは障害分離(Fault Isolation)ができていない証拠です。
2. 用いる原則
コンポーネントの凝集原則を、インフラストラクチャの文脈に拡張して適用します。
CCP (閉鎖性共通の原則 - インフラ拡張版)
「同じ理由で同時にスケーリングする必要がある、または同じ理由で障害が発生するコンポーネントは、同じ物理基盤にまとめる」。
逆に、スケーリング特性や障害理由が異なるなら分けるべき。
CRP (全再利用の原則 - インフラ拡張版)
「一緒に使われないものを一緒にデプロイ(配置)するな」。
サービスAしか使わない重いバッチ処理用DB設定を、サービスBも共有するインスタンスに適用してはいけない。
【重要】CAP定理と分散システムの落とし穴
同期通信は「一貫性(C)」を重視するが、「可用性(A)」と「分断耐性(P)」を犠牲にする。
ネットワークは信頼できないという前提に立ち、同期通信が必要な範囲を見極める。
バルクヘッド(隔壁)パターン
船の浸水を防ぐ隔壁のように、あるサービスの障害がシステム全体に波及しないよう物理的なリソースを分離する考え方。
3. 意思決定の3パターンと仮説構築
ECサイトを例に、「注文サービス」と「決済サービス」の関係で考えます。
4. 気をつけること
早すぎる最適化
まだトラフィックが少ないうちに、憶測でインフラを細かく分割しすぎると、運用コストと通信レイテンシだけが増大します。
なので、最初はモノリスや共有基盤から始め、痛みがデータとして現れてから分割を検討するのが賢明です。
ステップ2:運用フェーズでの仮説検証(検証フェーズ)
構築した仮説アーキテクチャに基づいて運用を開始した後、その判断が正しかったかを継続的に検証します。
1. メカニズム:障害注入と影響範囲の測定
平時のモニタリングに加え、意図的に障害を起こす(カオスエンジニアリングの初歩)ことで、境界設計の妥当性を検証します。
2-A. パターンC(切り離した)場合の検証:「本当に独立したか?」
「分離したこと」が、期待通りの効果を生んでいるかを確認します。
ブラスト・ラジアス(爆発半径)の測定
テスト: 決済サービスのDBを意図的にダウンさせる、または高負荷をかける。
検証メトリクス: 注文サービスの「可用性(Availability)」や「エラーレート」が悪化しないこと。注文サービスが(決済完了はできないまでも)注文受付を継続できること。
成功判断: 決済が死んでも注文は生きている。→ 仮説は正しかった。
失敗判断: 決済が死んだら注文APIもタイムアウトし始めた。→ 仮説は間違っていた(まだ隠れた同期結合がある)。
MTTR (平均復旧時間)
検証メトリクス: 決済サービスに障害が起きた際、復旧にかかる時間が、以前(共有基盤時代)より短縮されたか。
理由: 基盤が分離されていれば、他のサービスの影響を気にせず大胆な復旧作業(DB再起動など)ができるため、MTTRは短くなるはず。
2-B. パターンA/B(まとめた/まだ切り離さない)場合の検証:「共有の痛みは許容範囲内か?」
「分離しなかったこと」が、期待通りの効果を生んでいるかを確認します。
リソース競合のモニタリング
検証メトリクス: 共有DBのCPU使用率やIOPS。
着目点: 「注文サービスのセールによってDB負荷が高まり、決済サービスの処理遅延が許容閾値を超えた(SLA違反)」という事象が発生していないか。
失敗判断: 頻繁に「うるさい隣人」問題でSLA違反が起きる。→ 仮説(まだ切り離さなくて良い)を見直す時期が来た。
デプロイの独立性(運用メトリクス)
検証メトリクス: リードタイム(コードコミットから本番反映までの時間)。
着目点: 決済サービスの軽微な修正をデプロイするために、注文サービスチームとの綿密な調整や、同時リリースの待機時間が発生していないか。
失敗判断: 物理的な共有が原因で、組織的なデプロイの摩擦(調整コスト)が大きすぎる。→ インフラ分離を検討すべきサイン。
3. 気をつけること
データは嘘をつかないが、解釈は間違う
レイテンシが悪化した原因が、インフラ共有のせいなのか、単にアプリケーションコードのバグなのか、慎重な切り分けが必要です。
ビジネス要件の変化
当初は「同期が必須」だった要件も、ビジネス側と交渉することで「数秒の遅延は許容(結果整合性)」に変更できる場合があります。
要件が変われば、最適なインフラ境界も変わります。定期的な見直しが必要です。
まとめ
クリーンアーキテクチャでコードを綺麗に保っていても、インフラ層での結合はシステム全体の足を引っ張ります。
重要なのは、「論理的な美しさ」ではなく「物理的な制約(ネットワーク、リソース、障害)」を直視することです。
トレーシングデータやリソースメトリクスという「現実のデータ」を羅針盤とし、CCPやCAP定理、バルクヘッドといった原則を地図として、動的にインフラの境界線を引き直していくプロセスこそが、堅牢な分散システム運用への道となります。
