サードパーティによって公開されたJMSキューがあります。異なるマシンに複数のコンシューマーをセットアップし、特定のマシンのコンシューマーを1つだけにして、そのキューのメッセージを確認したいと思います。つまり、特定のマシンのコンシューマーがメッセージを受信しない場合、そのメッセージをキューから削除しないでください。これは達成可能ですか?
2 に答える
さて、あなたはこのセットアップのあなたの理由があるかもしれません、そしてそれは達成するのは簡単です。
私はローカルセッショントランザクションで行きます。どのサーバーがメッセージを消費しているかなど、いくつかの基準に従ってトランザクションをコミットまたはロールバックするのはかなり簡単です。ロールバックすると、メッセージは再びキューの最初になります。
サンプルコードは次のようになります。
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()によってこれを明示的に制御できます。トランザクションを使用しないことに意味はありません。謝辞は配達を保証するためだけにあります。
これを確認する別の方法は、転送キューの場合です。次のようにして、デザインに適用できます。
- サードパーティから公開されたキューにコンシューマを作成します。
- このコンシューマーには1つのジョブがあります。つまり、すべてのメッセージを他のキューに配布します。
- 実際のサブスクライバーがリッスンする追加のキューを作成します。
- メッセージリスナーをコーディングして、各メッセージを取得し、さまざまな宛先に転送します。
- 各リスナーを変更して、特定のキューから読み取るようにします。
これにより、すべてのリスナーにすべてのメッセージが表示され、すべてのトランザクションが期待どおりに機能し、メッセージの送信方法について何も想定しなくなります(たとえば、発行者側が実行している場合はどうなりAUTO_ACKNOWLEDGE
ますか?)