54

私のJMSアプリケーションでは、プロデューサーの一時キューを使用して、コンシューマーアプリケーションからの応答を受信できるようにしています。

このスレッドで言及されているのとまったく同じ問題に直面しています:http://activemq.2283324.n4.nabble.com/jira-Created-AMQ-3336-Temporary-Destination-errors-on-HA-failover-in -broker-network-with-Failover-tt-td3551034.html#a3612738

ネットワークで任意のブローカーを再起動すると、一時キューに応答を送信しようとしたときに、コンシューマーアプリケーションログに次のような多くのエラーが表示されていました。

javax.jms.InvalidDestinationException:
  Cannot publish to a deleted Destination: temp-queue://ID:...

それから私はそこでゲイリーの応答が使用を提案しているのを見ました

jms.watchTopicAdvisories=false

クライアントのurlパラメータとしてbrokerURL。この追加パラメーターを使用して、クライアントブローカーのURLをすぐに変更しました。ただし、このフェイルオーバーテストのためにネットワークでブローカーを再起動すると、次のようなエラーが発生します。

javax.jms.JMSException: 
  The destination temp-queue:
    //ID:client.host-65070-1308610734958-2:1:1 does not exist.

ActiveMQ5.5バージョンを使用しています。そして、私のクライアントブローカーのURLは次のようになります。

failover:(tcp://amq-host1:61616,tcp://amq-host2.tred.aol.com:61616,tcp://amq-host3:61616,tcp://amq-host4:61616)?jms.useAsyncSend=true&timeout=5000&jms.watchTopicAdvisories=false
 

さらに、4つのブローカーの1つに対するactivemq構成XMLがあります: amq1.xml

ここの誰かがこの問題を調べて、この設定で私が犯している間違いを教えてください。

アップデート:

コードで要求/応答をどのように実行しているかをさらに明確にするには、次のようにします。

  1. 私はすでにプロデューサーごとの宛先(つまり一時キュー)を使用しており、これをすべてのメッセージのreply-toヘッダーに設定しています。
  2. 私はすでにJMSCorrelationIDヘッダーでメッセージごとの一意の相関識別子を送信しています。
  3. 私の知る限り、CamelとSpringでさえ、要求/応答メカニズムに一時キューを使用しています。唯一の違いは、Spring JMSの実装では、メッセージごとに一時キューが作成および破棄されるのに対し、プロデューサーの存続期間中は一時キューが作成されることです。この一時キューは、クライアント(プロデューサー)アプリがシャットダウンしたとき、またはこの一時キューにアクティブなプロデューサーが接続されていないことを認識したときにAMQブローカーによって破棄されます。
  4. 私はすでにプロデューサー側の各メッセージにメッセージの有効期限を設定しているので、メッセージが長時間(60秒)キューに保持されないようになっています。
4

2 に答える 2

27

フェイルオーバーに役立つブローカー属性org.apache.activemq.broker.BrokerService#cacheTempDestinationsがあります:ケース。xml構成でこれをtrueに設定すると、クライアントが切断しても一時的な宛先はすぐには削除されません。高速フェイルオーバー:再接続により、一時キューから再度プロデュースおよび/または消費できるようになります。

キャッシュの削除を処理するtimeBeforePurgeTempDestinations(デフォルトは5秒)に基づくタイマータスクがあります。

ただし、注意点が1つありますが、その属性を利用するactivemq-coreのテストは見当たらないため、これについて保証することはできません。

于 2012-01-26T16:02:03.000 に答える
10

一時キューは、リクエスト/リプライ シナリオのリクエスター (プロデューサー) が接続するブローカー上に作成されます。それらは から作成されるjavax.jms.Sessionため、そのセッションが切断されると、クライアントの切断またはブローカーの障害/フェイルオーバーのいずれかが原因で、これらのキューは永久になくなります。コンシューマーの 1 人がそれらのキューに応答しようとしても、他のブローカーは意味を理解できません。したがって、あなたの例外。

これには、フェイルオーバーに対処し、すべてのメッセージを永続化する必要があると仮定して、アーキテクチャの考え方を変える必要があります。問題を攻撃する一般的な方法は次のとおりです。

  1. 返信先ヘッダーは、リクエスター プロセスに固有のキューを参照する必要がありますqueue:response.<client id>。クライアントの数が限られている場合、クライアント ID は標準名である可能性があり、クライアントの数が多い場合は UUID である可能性があります。
  2. 送信メッセージは、相関識別子を設定する必要があります (単に、リクエストとレスポンスを関連付けるための文字列です。結局のところ、リクエスタは同時に複数のリクエストを作成する可能性があります)。これはJMSCorrelationIDヘッダーに設定されており、リクエストからレスポンス メッセージにコピーする必要があります。
  3. リクエスターは、その相関 ID に基づいてメッセージ本文を要求元スレッドに返すリスナーをそのキューにセットアップする必要があります。元のスレッドへの相関 ID のマップのようなものを手動で管理する必要があるため (おそらく Futures を介して)、このために記述する必要があるマルチスレッド コードがいくつかあります。

これは、 Apache Camelがメッセージングを介したリクエスト/レスポンスのために採用したものと同様のアプローチです。

注意すべきことの 1 つは、クライアントが削除してもキューが削除されないことです。そのため、応答メッセージが消費されていない場合はブローカーから削除されるように、応答メッセージの存続時間を設定する必要があります。未使用のメッセージのバックログ。また、期限切れのメッセージを自動的に破棄するデッド レター キュー戦略を設定する必要があります。

于 2012-01-25T13:38:52.863 に答える