私のシナリオは-メッセージをキューに投稿し、メッセージが消費されたら、サードパーティのミドルウェアアプリケーションに送信します。そのミドルウェアアプリケーションがダウンしている場合、投稿されたメッセージは破棄されます。ミドルウェアアプリケーションがダウンしている場合にそのメッセージを失いたくないので、代わりに保留またはキューで待機させたいと思います。このシナリオをどのように処理するかを提案してください。
次のようにセッションを作成する必要があります。
_Session session = connection.createSession(false,
Session.CLIENT_ACKNOWLEDGE);
_
サードパーティのアプリにメッセージを配信しようとすると、次のようになります。
それが機能している場合は、メッセージを確認する必要があります。
ダウンしている場合は、確認しないでください。こうすることで、JMSプロバイダーが再配信できるようになり、メッセージが失われることはありません。 message.acknowledge();
また、これを見ることができます: JMS AUTO_ACKNOWLEDGEはいつ確認されますか?
JMSキューはメッセージストアではありません。
処理が引き続き失敗する「不良メッセージ」がある場合、JMSサーバー(構成されている場合)は必然的にそのメッセージを「デッドメッセージキュー」にダンプし、別のプロセスがメッセージを排出するまでゆっくりといっぱいになります。
悪いメッセージはキューをブロックする可能性があるため、キューに残したくありません(10人のコンシューマーがいて、上位10個のメッセージがすべて悪いと想像してください。したがって、すべてのプロセスは悪いメッセージに失敗し続けます-キューのストール)。
したがって、メッセージを例外シンクに格納するためのメカニズムが必要です。例外シンクでは、後で処理のためにメインキューにメッセージを挿入できます。
デッドメッセージキューはこのメカニズムではなく(JMSキューにメッセージを格納しないでください)、例外的なメッセージをより永続的なストレージ領域(つまり、dbテーブルなど)にルーティングするメカニズムである可能性があります。
そこに到達すると、それらは(自動、手動、その他何でも)精査され、再配信またはキャンセルされます。
ただし、重要な点は、このための外部メカニズムが必要であるということです。JMSサーバーだけでは、この種のメッセージに適した場所ではありません。
これは、セッション確認応答を使用して達成できます。このために、最初にSession.AUTO_ACKNOWLEDGEを使用するようにプロデューサーコードを変更します。キューセッションの作成中に、AUTO_ACKNOWLEDGEをfalseにします。それは消費者が認めなければならないことを意味します。コンシューマーがメッセージの確認応答を送信すると、メッセージはキューから削除されます。それ以外の場合は、キューに残ります。
以下はプロデューサーコードです。
try {
QueueConnectionFactory qcf = AppUtils.getQueueConnectionFactory();
Queue q = AppUtils.getDestination();
QueueConnection qConnection = qcf.createQueueConnection();
QueueSession qSession = qConnection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
QueueSender qSender = qSession.createSender(q);
qConnection.start();
TextMessage msg = qSession.createTextMessage("Hello");
qSender.send(msg);
qSender.close();
qConnection.close();
} catch (JMSException e) {
// log your error to log file
e.printStackTrace();
}
コンシューマー側でも同じことを行う必要があり、AUTO_ACKNOWLEDGEをfalseとしてキューセッションを作成します。
メッセージを処理した後、確認応答を送信してメッセージをキューから削除できます。そうしないと、メッセージはキューに残ります。
try {
QueueConnectionFactory qcf = getQueueConnectionFactory();
Queue q = getDestination();
QueueConnection qConnection = qcf.createQueueConnection();
QueueSession qSession = qConnection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
QueueReceiver qReceiver = qSession.createReceiver(q);
qConnection.start();
Message msg = qReceiver.receive();
// here send your message to third party application
//if your third party application is down
if(thirdpartyapp is down){
//here you can raise an exception
//or just do nothing
// you're not sending acknowledgement here so the msg will
//remain in the queue
}else{
msg.acknowledge();//here youre sending ack, so msg will be deleted
qReceiver.close();
qConnection.close();
}
} catch (JMSException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
メッセージを消費するアプリケーションがどのように設計されているかは明確ではありませんが、ローカルトランザクション内でメッセージを消費し、サードパーティのミドルウェアアプリケーションにメッセージを投稿するようにコンシューマーアプリケーションを変更することをお勧めします。投稿が成功した場合、JMSキューからメッセージを削除するトランザクションをコミットできます。アプリケーションがメッセージの投稿に失敗した場合は、トランザクションをロールバックするだけで、メッセージがJMSキューに再表示されます。そのメッセージは再び配信されます。