0

AMQP「トピック」を処理する機能を含むJavaEEアプリケーションを構築しています。私の考えは、のcontextInitializedメソッドを介して初期化されるListenerクラスを作成することですjavax.servlet.ServletContextEvent

このクラスは2つの別々のスレッドを実行します。1つはメッセージをリッスンして受信したメッセージをFIFOキューに追加し、もう1つはキューからのメッセージを処理します。この理由は、AMQPクライアントがメッセージ処理の遅延によって影響を受けるものではないためです。

複数の「リスナー」を持つ複雑なアプリケーションでは、非同期タスクを実行するスレッドが多数発生する可能性があります。このようにアプリケーションを複数のスレッドに分割することが合理的なアプローチであるかどうかをアーキテクチャの観点から知るのに十分な経験はありませんか?

たぶん、各メッセージは、キュープロセスではなく、「独自の」スレッドで処理する必要があります。アプリケーションフローを管理するための複数のスレッドの使用または私が提案したアプローチのいずれかに関するアドバイスやガイダンスをいただければ幸いです。

4

1 に答える 1

2

別々のスレッドで何かを実行しても、必ずしも高速になるとは限りません。

1 台のマシンで実行されるシステムのスループットは、マシンの処理帯域幅によって制限されます。つまり、コアの数と速度、メモリ システム、ディスクとネットワーク I/O などです。マルチスレッド アプリケーションでは、すべてのスレッドが効率的にリソースを共有します。たとえば、特定の瞬間にコアよりも多くの実行可能なスレッドがある場合、一部のスレッドはコードにスケジュールされるのを待っています。

2 つ目の問題は、通常、スレッドが相互に通信したり、共有データ構造を更新したりする必要があることです。これらは両方とも、ある種の同期を必要とします。これが頻繁に行われると、同期がボトルネックになり、スループットが低下する可能性があります。


では、これはあなたのシステムにどのように適用されますか? 潜在的な問題は、バックグラウンド処理を行っている余分なスレッドがリソースを使用することであり、スレッドの作業が多すぎる場合: - それらは追いつくことができず、キューの長さが不足する可能性があります制御不能になり、遅延が長くなり、さらに悪化します。これにより、リスナーが新しいメッセージを受け入れる機能が妨げられる可能性があります。

パフォーマンスの観点から、避けたいことの 1 つは、スレッドが多すぎることです。特定のポイント (アプリケーションによって異なります) を超えると、スレッドを追加すると、実際にはさまざまな理由でスループットが低下する可能性があります。経験則として、スレッド数をコア数の 1 ~ 2 倍に制限するようにしてください。

システムが処理できる以上のメッセージでいっぱいになる可能性が高いと思われる場合は、負荷を分散できるようにシステムを設計する必要があります。たとえば、新しいリクエストの受け入れを停止したり、既存のリクエストをダンプしたりします。無制限のキューや無制限の数のワーカー スレッドは必要ありません。これらは壊滅的なフィードバックやシステムの崩壊/高負荷下でのクラッシュにつながる可能性があります。(また、負荷が高いと競合が増え、検出されない同時実行バグによる障害の可能性が高くなることにも注意してください。)


アップデート:

  1. AMQP には「フロー フレーム」を使用したフロー制御メカニズムが組み込まれているようです。おそらく、独自のフロー制御/負荷管理を内部で行うのではなく、それを活用しようとしているはずです。
  2. メッセージの永続性自体は役に立ちません。大量のメッセージ トラフィックをバッファリングできますが、メッセージの生成速度と処理速度の不一致に対処するのには役立ちません。(持続メカニズムにより、メッセージ転送速度も遅くなりますが、おそらく気にする必要はありません。)
  3. 異なるサービスで処理の個別のフェーズを実行すると、スループットが向上しますが、反対に、メッセージングのオーバーヘッドが増えます。要するに、この種のパーティショニングは、スループットを向上させる代わりに、スループットを低下させる可能性があるということです。
  4. ソリューションをスケールアップしたい場合は、サーバーを複製できるように設計する必要があります。たとえば、新しいリクエストを 1 つのサーバーに送信する代わりに、独立した持続性バックエンドを持つ N 個のサーバーに分割します。
于 2012-09-19T01:31:56.063 に答える