サービス間通信で大量のデータを処理するために参照できるパターンまたは設計はありますか?.
私の使用例は、上流のフィードファイル(たとえば50kレコード)から分散システムにデータをインポートすることです。そのため、これらのレコードは複数のサービスで終了します。各レコードは、システム内のエンティティのインスタンスを表します。例ユーザー。
エンティティの単一インスタンスである他のユースケースでは、RabbitMQを使用した非同期通信を使用します。
私たちはレコードをバッチ処理することを考えていました。たとえば、メッセージごとに1000レコードです。キュー内に管理可能なメッセージのボリュームがあり、消費サービス内で一括挿入/更新を利用できるようにするためです。
1000レコードのバッチがいずれかのサービスで部分的に成功した場合はどうなるでしょうか。
REST呼び出しを行うことはオプションですが、非同期通信ほどスケーラブルではありません。
誰もが以前に同様のユースケースに遭遇した場合、どのようにそれを処理しましたか?
私は同様の要件を持つシステムで作業しています-パートナーは、処理する10〜1,000,000レコードのいずれかを含むファイルをドロップします。パートナーによっては、ファイルを1日に1回ドロップするものもあれば、1時間に1回ドロップするものもあれば、アドホックなものもあります。
私たちのシステムはEdgeでデータ統合ツールを使用してファイルを検証し、(最大で)1000レコードのバッチに分割し、各バッチを正規化されたJSONペイロードに変換し(異なるパートナーは異なるデータ形式を持つことができます)、RESTオーケストレーションサービスのエンドポイント。内部的には、オーケストレーションサービスはマルチスレッド化されているため、バッチは並列処理されます。オーケストレーションサービスは、バッチ内の各レコードのステータスを含む応答を返します。データ統合ツールは、レコードごとに成功を記録し、再試行のためにレコードをスケジュールするか、レコードを端末障害バケットにルーティングするのに十分スマートです。
オーケストレーションサービスで使用される重要なサービスはすべて同期していますが、重要ではない処理にメッセージングを使用する場合もあります。このアプローチは私たちにとってうまくいきます。
あなたの懸念のいくつかに対処します:
最初に、RESTはメッセージングほどスケーラブルではないと言います。 HTTPはリクエストごとに接続を作成するのに対し、メッセージブローカーは通常、セットアップ/ティアダウンのオーバーヘッドを回避するために接続を開いたままにしておくという事実を暗示していると思います。これが、レコードをバッチで送信する理由です-多くのレコードでオーバーヘッドを償却するためです。メッセージングを使用する場合は、バッチ処理がさらに複雑になることを保証するのに十分なバッチ処理の利点がない場合があります。
バッチの成功/失敗にオールオアナッシングアプローチを採用すると、システムが詰まる可能性があると述べました。私たちは同意したので、「良い」および「端末障害」レコードが一度だけ処理されるようにシステムを設計しました-何らかの一時的なエラーが発生したレコードのみが再試行されます。間違いなく、このロジックは、非同期で処理されているすべての「処理中」のレコードを追跡するよりも、すべての重要な処理を同期して実装する方が簡単です。
最後に、レコードが廃棄されるのを待っている間に一部のサービスが更新されたため、再試行されたレコードには問題があると述べました。それは完全に別の問題です。システムでこのような事態が発生する可能性がある場合は、サービスのバージョンをmustに更新して、プロセス全体の古いバージョンによって部分的に処理されたレコードが残りのサービスの正しいバージョンを使用して完了するようにします。すべてのデータがシステムに流れ、古いバージョンが不要になった場合にのみ、データが削除されます。 APIに重大な変更を加えることを禁止するバージョン管理ポリシーがあります。重大な変更が必要な場合、APIの新しいバージョンが作成され、その古いバージョンは、すべてのクライアントが削除された後にのみ削除されますknow新しいバージョンに更新されました。
お役に立てれば...
データを送信するのではなく、データへのリンクまたはデータを取得するための指示を送信します。イベントでワンタイムパスワードまたはバッチIDを送信すると便利な場合があります
つまり.
{
"sync" : {
"source" : "http://api.contoso.com/api/v1/users?batchId=36DA01F-9ABD-4D9D-80C7-02AF85C822A8"
}
}
このように、イベントプロセッサが実行されるまでデータの取得が遅延し、データが無効になる可能性が低くなります。
また、そのバッチIDを削除するなどして、ソースで操作をキャンセルする可能性も残します