web-dev-qa-db-ja.com

同時同期要求-JMS / ActiveMQを使用した応答-パターン/ライブラリ?

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

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

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

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

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

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


関連SO質問:

23
joshwa

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

そうは言っても、この演習全体で、JMSとHTTPの違いを再考することになります... :)

3
joshwa

過去のプロジェクトでは、同期WSリクエストがAsync req/resJMSメッセージのペアで処理されるという同様の状況がありました。当時はJbossJMS implを使用し、一時的なdestinationsを使用していました。

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

そのソリューションはすべて自家製でしたが、応答をリクエストに一致させる問題を解決する、Niceブロッキングマップの実装に出くわしました。

BlockingMap

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

4
maasg

私はまだCamelを使用することを考えており、おそらくSpring Remotingを使用せずに、生のProducerTemplatesだけでスレッドを処理させます。

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

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

4

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

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

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

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

0
GullerYA

私は常に要求/応答にCorrelationIDを使用しており、パフォーマンスの問題が発生したことはありません。なぜそれがパフォーマンスの問題になるのか想像できません。どのメッセージングシステムでも非常に高速に実装でき、非常に重要な機能をうまく実装できるはずです。

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

0
ams