2

サードパーティによって公開されたJMSキューがあります。異なるマシンに複数のコンシューマーをセットアップし、特定のマシンのコンシューマーを1つだけにして、そのキューのメッセージを確認したいと思います。つまり、特定のマシンのコンシューマーがメッセージを受信しない場合、そのメッセージをキューから削除しないでください。これは達成可能ですか?

4

2 に答える 2

1

さて、あなたはこのセットアップのあなたの理由があるかもしれません、そしてそれは達成するのは簡単です。

私はローカルセッショントランザクションで行きます。どのサーバーがメッセージを消費しているかなど、いくつかの基準に従ってトランザクションをコミットまたはロールバックするのはかなり簡単です。ロールバックすると、メッセージは再びキューの最初になります。

サンプルコードは次のようになります。

public class MyConsumer implements MessageListener{ 
  Session sess;

  public void init(Connection conn, Destination dest){
    // connection and destination from JNDI, or some other method.
    sess = conn.createSession(true, Session.AUTO_ACKNOWLEDGE);
    MessageConsumer cons = sess.createConsumer(dest);
    cons.setMessageListener(this);
    conn.start();
  }

  @Override
  public void onMessage(Message msg) {
    // Do whatever with message
    if(isThisTheSpecialServer()){
       sess.commit();
    }else{
       sess.rollback();
    }
   }

   private boolean isThisTheSpecialServer(){
      // figure out if this server should delete messages or not
   }
}

JTAを使用してJavaEEコンテナ内でこれを実行していて、UserTransactionsを使用している場合は、UserTransaction.setRollBack();を呼び出すだけです。または、宣言型トランザクションを使用している場合は、ランタイム例外をスローしてトランザクションを失敗させ、メッセージを読んで処理を完了したら、メッセージをキューにロールバックすることができます。このアプローチでは、データベースの変更もロールバックされることに注意してください(ローカルJMSトランザクションではなくJTAを使用している場合)。

アップデート:

これは、確認応答ではなく、トランザクションを使用して実際に行う必要があります。

このトピックの要約(ActiveMQの場合ですが、一般的にJMS用に書かれています)はここにあります。 http://activemq.apache.org/should-i-use-transactions.html

この動作がすべてのJMS実装と一致しているかどうかはわかりませんが、ActiveMQの場合、Session.CLIENT_ACKNOWLEDGEMENTでトランザクションなしのセッションを使用しようとすると、実際には期待どおりに動作しません。読み取られたが確認されていないメッセージはまだキューにありますが、最初のコンシューマーへの接続が切断されるまで(つまり、connection.close()、クラッシュ、または似ている)。

ローカルトランザクションを使用すると、session.commit()およびsession.rollback()によってこれを明示的に制御できます。トランザクションを使用しないことに意味はありません。謝辞は配達を保証するためだけにあります。

于 2012-07-15T13:54:12.170 に答える
0

これを確認する別の方法は、転送キューの場合です。次のようにして、デザインに適用できます。

  1. サードパーティから公開されたキューにコンシューマを作成します。
  2. このコンシューマーには1つのジョブがあります。つまり、すべてのメッセージを他のキューに配布します。
  3. 実際のサブスクライバーがリッスンする追加のキューを作成します。
  4. メッセージリスナーをコーディングして、各メッセージを取得し、さまざまな宛先に転送します。
  5. 各リスナーを変更して、特定のキューから読み取るようにします。

これにより、すべてのリスナーにすべてのメッセージが表示され、すべてのトランザクションが期待どおりに機能し、メッセージの送信方法について何も想定しなくなります(たとえば、発行者側が実行している場合はどうなりAUTO_ACKNOWLEDGEますか?)

于 2012-07-15T19:07:11.253 に答える