web-dev-qa-db-ja.com

イベントソースアーキテクチャのマイクロサービスは、REST / gRPC / etcを介して互いに直接通信すべきではありませんか?

イベントソースアーキテクチャに頭を抱えようとしています。

一般的なアドバイスは、情報ができるだけ少ない小さなイベントを持つことです(他のサービスが独自のデータを保存できるようにするためにすべてが含まれる大きなイベントとは対照的です)。

明らかにサービス間の結合を減らすことが推奨されます。そのため、あるサービスから別のサービスに直接呼び出しを行わないこと、およびREST/qRPCなどを行うことを推奨することは一般的です。別のサービスの呼び出しは悪いことです。人々がイベントをペイントするのは、サービス間で発生する唯一の通信であるようです。

ただし、小さなイベントを発生させたり、サービス間で直接通信を行ったりすることはできません。例えば注文サービスは、製品サービスに保管されている製品の名前を知る必要がある場合があります。

イベントソースアーキテクチャのマイクロサービスは、REST/gRPCなどを介して互いに直接通信すべきではありませんか?

2
nanotek

マイクロサービスを使用する場合、最大の問題はリクエストの処理にかかる時間です。つまり、同期応答時間を管理する必要があります。重要なことは、設計決定の影響を理解することです。ユーザーがWebサイトから要求を行うと、有効な応答が得られるまでに時間がかかります。

非同期呼び出し

非同期呼び出しを使用すると、他のすべてのサービスが追いつくのを許可しながら、呼び出し元にできるだけ早く応答を提供できます。この概念は、最終的な整合性として知られています。一般に、メッセージキューまたは同様のサービス(Kafkaなど)を使用して、データが変更されたことを他のサービスに通知します。

  • メッセージに基づいて行動するために必要な情報のみを提供したいとします。
    • 他のサービスが、更新された残りの情報を取得するためにコールバックする必要がある場合、何も保存しません。
  • あなたはあなたの保証が何であるかを決定しなければなりません。
    • ほとんどのメッセージキューの実装では、サービスが一時的に停止していても、メッセージの配信が保証されます
    • マイクロサービスがメッセージに対して何もできない場合は、サービスがキューをドレインするか、バックプレッシャーを適用することが問題ないかを判断する必要があります
  • ユーザーに回答を返す必要がない領域の非同期呼び出しを保存します
  • キャッシュエントリの更新は非同期で行うのが最適です

同期呼び出し

あるマイクロサービスが別のマイクロサービスを呼び出せない理由はありません。ブラウザーはそれを実行でき、サービスも実行できます。トレードオフが何であるかを知る必要があるだけです。

  • リクエストチェーンはコードの脆弱性を増加させます(つまり、あるサービスが別のサービスを呼び出し、別のサービスが別のサービスを呼び出します)。
  • 要求の連鎖は、ユーザーへの応答を返すのにかかる時間も増加させます...
    • 呼び出しごとにシリアライゼーション/デシリアライゼーションのオーバーヘッドがあります
    • パスの各ステップで処理が発生しています
  • とはいえ、低レイテンシのリクエストチェーンが必ずしも悪であるとは限りません
    • APIゲートウェイ/リバースプロキシを使用すると、マイクロサービスインスタンスへの呼び出しの負荷を分散できます
    • 一部のエンドポイントでは、他のエンドポイント(GraphQLフェデレーションなど)への呼び出しを最適化できます
  • デフォルトの応答で応答するか、マイクロサービスの別のインスタンスで要求を再試行するには、サーキットブレーカーパターンを使用する必要があります
    • ガベージコレクションやその他の非決定的な理由により、サービスが応答しない状態でスタックすることがある
    • 応答を待つ用意がある最大時間を設定することにより、ユーザーが待機する必要のある期間を制限します

ボトムライン

おそらく、ソリューションで非同期呼び出しと同期呼び出しの両方を慎重に使用する必要があります。それで大丈夫です。他のサービスに非同期に通知する主な利点は、ユーザーに応答を送信する前に、すべてが一度に更新されるのを待つ必要がないことです。もう1つの利点は、計算が完了するのを待つペナルティを発生させることなく、データが変更されたりアクセスされたりしたときに、複雑なアルゴリズムを提供できることです。

ユーザーを待機させる時間が短いほど、Webアプリケーションの応答性が高くなります。リクエストを処理する最も適切な手段を使用します。

3
Berin Loritsch

イベントソースアーキテクチャに頭を抱えようとしています。

ここで説明しているのはイベント駆動アーキテクチャであることに注意してください。イベントソースは本当に別のことを意味します。

マイクロサービスアーキテクチャについて説明する場合、一度に1つのマイクロサービスを再デプロイできると期待しています。 Autonomousマイクロサービスは、ネイバーが再デプロイされている場合でも進行できる必要があります。これにより問題が発生します-サービスからの応答を待っている場合、サービスは進行できず、サービスは再デプロイされます。

通常の答えは、データのコピーを処理することです-私のサービスはあなたから必要な情報のコピーをキャッシュしたので、進歩することができます。言い換えると、同期ではなく非同期でメッセージを交換することに同意した場合、1つのマイクロサービスが利用できないときにカスケード停止が発生することはありません。

イベントは「単なる」メッセージです。システム内のマイクロサービス間でメッセージを交換する方法が必要です。直面する状況に応じて適切なトランスポートを選択します。たとえば、Atom Syndication/Atom Pubは、多くの組織がよく理解しているコレクションにメッセージを追加するための素晴らしい標準を提供しますが、同じ会社が所有し、互いに近接して実行されているマイクロサービスのクローズドコレクションを処理している場合、この種のトレードオフです。別の方法は、メッセージバスを使用することです。または、マイクロサービスに共通のメッセージストアを共有させることもできます。

ただし、小さなイベントを発生させたり、サービス間で直接通信を行ったりすることはできません。例えば注文サービスは、製品サービスに保管されている製品の名前を知る必要がある場合があります。

それはある程度責任の分離から生じます-なぜ注文サービスは不透明な製品ID以上のものを必要とするのですか?そして、その結合は、どこかに設計上の欠陥があることを示していますか?

昨年のデータ設計の多くは、スペースに厳しく制約されていました。スペースを節約するために、各ファクトの単一のコピーが必要でした。今日の取引は異なり、ストレージが安価なため、データのコピーを1つ用意することはそれほど重要ではありません(どのデータがコピーでどれが信頼できるかについて考える必要があります)。

ですから、注文サービスに製品名が必要の場合、その情報を提供するメッセージがどこかにあるはずです。したがって、そのメッセージは、必要な場所に到達するために何らかのトランスポートを必要とします。

Pat Hellandも参照: 外側のデータ...

3
VoiceOfUnreason