分散システムでのエラー処理


8

これは、Javaアプリケーションでの2つの分散コンポーネントの一般的なシーケンスです。

1  A sends request to B
2      B starts some job J in parallel thread
3      B returns response to A
4  A accepts response
5      Job finishes after some time
6      Job sends information to A
7  A receives response from a Job and updates

これは、すべてが機能すると仮定した場合の理想的なシナリオです。もちろん、実生活は失敗に満ちています。たとえば、最悪のケースの1つは、#6単にネットワークが原因で失敗した場合です。ジョブは正しく実行されましたが、ジョブAについて何も知りません。

このシステムのエラーを管理する方法についての軽量なアプローチを探しています。多くのコンポーネントがあるため、エラー処理のためにそれらをすべてクラスター化しても意味がありません。次に、同じ理由で各コンポーネントに再度インストールされる分散メモリ/リポジトリの使用を取りやめました。

私の考えは、Bに1つの絶対状態を持ち、Aに永続状態を決して持たないという方向に向かっていAます。これは、次のことを意味します。

  • 作業ユニットに#1マークを付ける前A、つまり変更が開始されようとしています
  • Bこの状態のマークを解除することのみ可能です。
  • AB状態を更新するために、いつでも情報を取得する場合があります。
  • で同じユニットの新しい変更を呼び出すことはできませんA

どう思いますか?この種のシステムのエラーを緩和する軽量の方法はありますか?


これは古い質問です。良い解決策を見つけましたか?...もしそうなら、それを共有できますか?
svidgen 2018年

回答:


2

Aの永続的なログに追加するだけで十分です。これは、再起動とネットワークパーティションに対処して、最終的な一貫性を実現したり、破損を通知してそのような収束を防止します。償却グループコミットを使用すると、ログエントリを永続化するための書き込みが1回未満で済みます。

あなたは、Bにマークのない状態の責任を負わせることを提案しました。同意しません。Aだけが新しい作業を認識し、Aだけがそれを追跡し、タイムアウトなどのエラーを報告する必要があります。Bはべき等メッセージをAに送信し、Aは状態を更新し、必要に応じて間隔を置いて再クエリします。

ステップ0で、Aは新しい要求を認識し、ログに記録します。これは、Aが後で期限までに実行しなければならない義務を構成します。Aは、要求処理が完了したことをAが知るまで、後続のステップを継続的に実行し、繰り返します。

一部のリクエストは他のリクエストよりも長くなります。処理時間の見積もりは、AとBで利用できるようになります。おそらく処理が進むにつれて修正されます。このような推定はAにフィードバックされる可能性があるため、誤検知タイムアウトが発生することはめったにありません。「まだ機能している、まだ機能している」というキープアライブメッセージと考えてください。


1

プッシュ戦略の代わりにプルを採用します。各パーツに他のパーツからの変更をプルさせ、独自のレコードを更新します。

  • AはBがすべきことをキューに記録する
  • BはAのキューからプルして作業を行います
  • Bはキューに行ったことをログに記録します
  • AはBのキューからプルして、ジョブの結果が何であるかを知る

(私は単語キューを使用していますが、ログまたはトピックで代用できます。)

キューをサービスにベイクするか、個別のメッセージブローカーを用意できます。サービスに組み込まれた実装は、GET /jobrequests?from=<timestamp>(Bが最後に処理されたジョブリクエストのタイムスタンプを追跡する)と同じくらい簡単です。

このようなアーキテクチャのトリッキーな部分は、少なくとも1回のセマンティクスと最低1回のセマンティクスを決定することです。具体的には、Bがアイテムをキューからプルし、実行中にクラッシュした場合、どうなりますか?2つの可能性があり、どちらが最適かは、ユースケースによって異なります。

  • At-least-once:Bは、アクションの完了後にキューのどのポイントに到達したかをコミットするだけであり、アクションを2回実行するリスクがあります。べき等になるようにアクションを設計する場合、このアプローチを使用して1回限りの動作を実現できます。(このシナリオでは、kafkaを使用します。)
  • 最大で1回:Bはすべてのキューアイテムを1回だけ消費します。実行中にクラッシュした場合、アイテムは実行されません。

このアプローチの利点:

  • キューを消費するサービスは、キュープッシュが発生するために稼働している必要はありません。これは、Aが作業している間にBを再起動するか、Bが作業している間にAを再起動することが自由であることを意味します。バックグラウンドサービスの冗長ホスティングは、全体的な応答時間を確保するためにのみ必要であり、信頼性のある操作ではありません。
  • キューアイテムのプルの速度はコンシューマが制御できるため、キューの負荷ピークを一時的にバッファリングできます。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.