Java 如果在使用消息后出现任何错误,如何在JMS消息队列中保存消息?
我的场景是-我将消息发布到队列中,一旦消息被使用,我就将其发送到第三方中间件应用程序。如果那个中间件应用程序关闭了,那么我发布的消息就不见了。我不希望在中间件应用程序关闭时丢失该消息,而是希望它处于等待状态或在队列中等待。请提出建议,如何处理这种情况?尽管目前还不清楚您的应用程序是如何设计的,但我建议您修改消费者应用程序以使用本地事务中的消息,并将消息发布到第三方中间件应用程序。如果post成功,那么您可以提交将从JMS队列中删除消息的事务。若您的应用程序无法发布消息,您可以简单地回滚事务,这将使消息重新出现在JMS队列中。该消息将再次发送。您应该创建如下会话:Java 如果在使用消息后出现任何错误,如何在JMS消息队列中保存消息?,java,jms,message-queue,middleware,Java,Jms,Message Queue,Middleware,我的场景是-我将消息发布到队列中,一旦消息被使用,我就将其发送到第三方中间件应用程序。如果那个中间件应用程序关闭了,那么我发布的消息就不见了。我不希望在中间件应用程序关闭时丢失该消息,而是希望它处于等待状态或在队列中等待。请提出建议,如何处理这种情况?尽管目前还不清楚您的应用程序是如何设计的,但我建议您修改消费者应用程序以使用本地事务中的消息,并将消息发布到第三方中间件应用程序。如果post成功,那么您可以提交将从JMS队列中删除消息的事务。若您的应用程序无法发布消息,您可以简单地回滚事务,这将
Session session = connection.createSession(false,
Session.CLIENT_ACKNOWLEDGE);
当您尝试将邮件发送到第三方应用程序时:
- 如果它起作用,你应该确认消息
- 如果它关闭了,您不应该对其进行确认,这样JMS提供程序将能够重新传递它,并且消息不会丢失<代码>消息。确认()代码>
另外,您可以查看以下内容:这可以通过使用会话确认来实现。为此,请首先修改生产者代码以使用Session.AUTO\u 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();
}
下面是生产商代码
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服务器(如果配置)将不可避免地将该消息转储到一个“死消息队列”,该队列将慢慢填满,直到另一个进程将其耗尽 您不希望将坏消息保留在队列中,因为它们可能会阻塞队列(假设您有10个消费者,前10条消息都是坏消息,因此所有进程所做的就是继续处理坏消息——使队列暂停) 因此,您需要某种机制来将消息存储到异常接收器中,然后将它们注入到主队列中进行处理
死消息队列不是这种机制(不要将消息存储在JMS队列中),相反,它可以是一种将异常消息路由到更永久的存储区域(即db表或其他东西)的机制 一旦到了那里,他们可以被审查(自动,手动,无论什么),或者重新交付或取消
但关键的一点是,您需要一个外部机制来实现这一点,JMS服务器本身并不是此类消息的合适场所。您的持久消息-->第三方如何?第三方的ack系统是什么?i、 e.你怎么知道他们是不是站起来了,即使他们站起来了,他们也没有出错并扔掉你的味精--你们和第三方有什么合同?我正在使用RESTfulWeb服务合同与第三方应用程序交互。如果服务器关闭,它将尝试连接几次,然后如果失败或连接丢失,我们将收到错误消息。您是否可以设置死信队列,然后定期将这些消息移回主队列?“不要将消息存储在JMS队列中”您能进一步解释这一点吗?队列可以是持久的,那么为什么不存储在其中呢?在某些情况下,您需要按照严格的顺序处理消息。在这种情况下,只要错误消息没有被成功消费,它们就会被保留在队列中。您能否给出一个代码示例,说明您可以实现上述功能?