24

ユーザーがリクエストを送信すると、リモートサービスにJMSメッセージを送信し、応答を待つWebアプリがあります。(非同期リクエストもあり、メッセージの再生などのためにさまざまな機能が設定されているため、HTTPではなくJMSを使用することをお勧めします)

JMSを使用して要求応答を実装するにはどうすればよいですか?」、ActiveMQは、リクエストごとの一時キュー、またはJMSCorrelationIDにセレクターを持つ一時コンシューマーのいずれかのアイデアを思いとどまらせるようです。これは、それらのスピンアップに伴うオーバーヘッドのためです。

ただし、プールされたコンシューマーを応答に使用する場合、応答コンシューマーから元の要求スレッドにディスパッチするにはどうすればよいですか?

私は確かに自分のスレッドセーフなコールバック登録/ディスパッチを書くことができましたが、私よりもよく知っている誰かによってすでに書かれていると思われるコードを書くのは嫌いです。

そのActiveMQページは、2006年以降更新されていないLingoと、多くの落とし穴のバグのために私のチームによって厳しく禁止されているCamelSpringRemotingを推奨しています

このパターンを実装するライブラリの形式で、またはJMSを介した同期要求/応答をシミュレートするための別のパターンの形式で、より良い解決策はありますか?


関連するSOの質問:

4

5 に答える 5

4

過去のプロジェクトでは、同期 WS 要求が Async req/res JMS メッセージのペアで処理された、同様の状況がありました。当時は Jboss JMS impl を使用していましたが、一時的destinationsにオーバーヘッドが大きくなりました。

最終的にスレッドセーフなディスパッチャーを作成し、JMS の応答が届くまで WS を待機させました。CorrelationID を使用して、応答を要求にマップし直しました。

その解決策はすべて自作のものでしたが、応答を要求に一致させる問題を解決する素晴らしいブロッキング マップ impl に出会いました。

ブロッキングマップ

ソリューションがクラスター化されている場合は、応答メッセージがクラスター内の正しいノードにディスパッチされるように注意する必要があります。私は ActiveMQ を知りませんが、JBoss メッセージングには、クラスター化可能な宛先の内部でいくつかの不具合があったことを覚えています。

于 2012-08-01T10:21:34.200 に答える
4

私はまだ Camel を使用することを考えており、おそらくスプリング リモーティングを使用せずに生の ProducerTemplates だけで、スレッド化を処理させます。

Camel には、トピックに関する優れたドキュメントがいくつかあり、ActiveMQ と非常にうまく連携します。 http://camel.apache.org/jms#JMS-RequestreplyoverJMS

セレクター ベースのコンシューマーとオーバーヘッドのスピンアップに関する質問については、ActiveMQ ドキュメントで実際に述べられていることは、地球の反対側または高遅延ネットワーク上にある可能性がある ActiveMQ ブローカーへのラウンドトリップが必要であるということです。この場合のオーバーヘッドは、AMQ ブローカーへの TCP/IP ラウンドトリップ時間です。私はこれをオプションと考えます。何度も使用して成功しました。

于 2012-08-01T20:03:54.470 に答える
3

同僚が潜在的な解決策を提案しました。つまり、webapp スレッドごとに 1 つの応答キュー/コンシューマーであり、その特定のスレッドが所有する応答キューに戻りアドレスを設定できます。これらのスレッドは通常、存続期間が長い (そして、後続の Web 要求に再利用される) ため、スレッドがプールによって生成されたときのオーバーヘッドのみを負担する必要があります。

とはいえ、この演習全体で、JMS と HTTP の違いを再考する必要があります... :)

于 2012-08-03T01:33:51.817 に答える
0

それは古いものですが、私は何か他のものを探してここに着陸し、実際にいくつかの洞察を持っています (うまくいけば誰かに役立つでしょう)。

クラスターのノード間通信用のシャーシである Hazelcast を使用して、非常によく似たユースケースを実装しました。本質は 2 つのデータセットです。応答用の分散マップが 1 つ、応答待機者の「ローカル」リストが 1 つ (クラスタ内の各ノード上)。

  • 各リクエスト (Jetty から独自のスレッドを受け取る) は、ローカル awaiter のマップにエントリを作成します。エントリには明らかに相関UIDとセマフォとして機能するオブジェクトがあります
  • 次に、リクエストがリモート (REST/JMS) にディスパッチされ、元のスレッドがセマフォで待機を開始します。UID はリクエストの一部である必要があります
  • remote は応答を返し、相関する UID を使用して応答マップに書き込みます
  • 応答マップがリッスンされています。新しく来る応答の UID がローカル awaiters のマップで見つかった場合、そのセマフォが通知され、元の要求のスレッドが解放され、応答マップから応答が取得され、クライアントに返されます。

これは一般的な説明です。関心がある場合に備えて、いくつかの最適化を行って回答を更新できます。

于 2017-08-11T07:22:53.087 に答える
0

私は常にリクエスト/レスポンスに CorrelationID を使用してきましたが、パフォーマンスの問題は一度もありませんでした。なぜそれがパフォーマンスの問題になるのかまったく想像できません。どのメッセージングシステムでも実装するのが非常に高速であり、実装するのに非常に重要な機能である必要があります。

http://www.eaipatterns.com/RequestReplyJmsExample.htmlには、replyToQueue または correlationID を使用した 2 つのメイン ストリーム ソリューションがあります。

于 2012-08-01T08:45:09.977 に答える