私の知る限り、マイクロサービスアーキテクチャでサービス通信を処理する場合、2つの一般的に使用されるパターンがあります。
A
は一部のデータを処理し、Service B
にそのデータを処理するように指示する必要があります。 A
はB
のエンドポイントURLを知っており、それを直接呼び出します。A
は共通のキューでメッセージを送信し、B
はそれを受信して何をすべきかを認識します。どちらにも欠点があります。
B
を変更する場合、B
とやり取りする他のすべてのサービスも適応および再デプロイする必要がある可能性があります。それで、サービス通信を管理する好ましい方法は何ですか?
失敗を減らすことができる代替手段はありますかandマイクロサービス間の密結合を回避しますか?
当然のことながら、メッセージの受け渡し専用のコンポーネントを持つことは、すべてのサービスがすべての共同サービスに正確に到達する方法を知る責任を持つよりも間違いなく優れています。したがって、メッセージキュー、通信バスなどをお勧めします。
そして、それらが単一障害点になるとしたら?さて、堅牢性とスケーリングのために常に行うことを実行します。メッセージキューの複数のインスタンスを展開します。ご使用の環境でanyを維持できない場合は、とにかく有用な作業が行われない可能性があります。問題が解決しました。
さて、サービス[〜#〜] b [〜#〜]が失敗し、応答しないとしましょう。現在、プロセス全体は続行できません。これは、[〜#〜] b [〜#〜]に依存して作業の一部を実行しているためです。 [〜#〜] b [〜#〜]が単一障害点ではないのはなぜですか?
共通のバス(またはオーケストレーターなど)を使用することで得られる利点は、単一のサービスのダウンタイムを処理できることです。キューは[〜#〜] b [〜#〜]に送信されたメッセージを、サービスがバックアップされて消費できるようになるまで保持できます。
また、単一の高可用性システムを稼働させ続ける可能性は、所有者が異なるN個の異なるシステムについて心配する必要があるよりも優れています。
これが Martin Fowlerによる興味深い投稿 です。これは、使用できると思うイベントを使用してマイクロサービスのソリューションを提供します。
どちらのトポロジが最適かは、通信の形態に大きく依存します。
たとえば、サービス間の広範な会話を必要としない自己完結型のメッセージを介して送信している場合は、ブローカーのメッセージバスが適切に機能します。これは、メッセージが複数のサービスに到達する必要がある場合、またはどのサービスがメッセージを取得するかを知らない場合に特に当てはまります。回復力は、ほとんどの一般的なメッセージブローカーが処理できるクラスター化されたブローカーセットアップで管理できます。
ただし、通信がほとんど双方向である場合は、ピアツーピアが適しているかもしれません。これは、サービス間でデータをストリーミングする場合に特に当てはまります。適切なパートナーを識別するためにディスカバリー・サービスを使用するなど、カップリングを軽減するためのさまざまな技法があります。インターフェイスの結合を制限する一般的な手法もあります。たとえば、RESTのようなAPIを持ち、ビジネスコミュニケーションに拡張可能な宣言型インターフェースを使用します。 JSONは一般的なフォーマットで、XMLはその前などでした。
メッセージバスを介してピアツーピアを実行できないと言っているわけではありませんが、複雑になる可能性がある多くのセッション状態を管理することになります。通信がほとんどピアツーピアのイベントである場合でも、1つのメッセージングシステムだけを維持するためにこれを行うことをお勧めします。
同様に、ほとんどがメッセージパッシングでストリーミングしている場合、同じ理由でイベントプロトコルをストリーミングプロトコルに埋め込むこともできます。
そして、これらはあなたの唯一のオプションではありません。複雑なセットアップの場合、私は ZeroMQ を使用するのが非常に好きです。1つの通信「ファブリック」を使用しますが、必要に応じて適切なトポロジを適用します。
要約すると、最適なメッセージングトポロジは、メッセージの性質によって異なります。正解は1つではありませんが、良い面は十分に踏み込んだ道です。非常に異常なことをしているのでない限り、賢明な緩和策を備えたすぐに使えるすぐれたソリューションを入手できるはずです。