【发布时间】:2020-08-06 23:03:09
【问题描述】:
应用中的工作版本
- IBM AllClient 版本:'com.ibm.mq:com.ibm.mq.allclient:9.1.1.0'
- org.springframework:spring-jms : 4.3.9.RELEASE
- javax.jms:javax.jms-api : 2.0.1
我的要求是,如果由于消费者不可用(例如数据库不可用)而导致消息处理失败,则消息保留在队列中或放回队列中(如果这甚至可能的话)。这是因为消息的顺序很重要,消息必须按照接收到的顺序被消费。 Java 应用程序是单线程的。
我已经尝试了以下
@Override
public void onMessage(Message message)
{
try{
if(message instanceOf Textmessage)
{
}
:
:
throw new Exception("Test");// Just to test the retry
}
catch(Exception ex)
{
try
{
int temp = message.getIntProperty("JMSXDeliveryCount");
throw new RuntimeException("Redlivery attempted ");
// At this point, I am expecting JMS to put the message back into the queue.
// But it is actually put into the Bakout queue.
}
catch(JMSException ef)
{
String temp = ef.getMessage();
}
}
}
我已经在我的 spring.xml 中为 jmsContainer bean 设置了这个。
<property name="sessionTransacted" value="true" />
上面的代码有什么问题?
如果将消息放回队列中是不切实际的,如何浏览消息、处理它,如果成功,拉取消息(因此它被消费并且不再在队列中)? IBM Provider for JMS 是否支持这种场景?
IBM MQ 本地队列有 BOTHRESH(1)。
【问题讨论】:
-
这不是本地队列。队列管理器和队列位于单独的服务器上。无论如何,有毒消息在我们的系统中很少见。更令人担忧的是消息被丢弃,因为它们无法插入数据库/或消费。换句话说,事务支持。但我对 JAVA 的 IBM MQ 类不熟悉(我们的应用程序是 Spring 应用程序,因此所有对象实例化都由 Spring 完成),并且不确定 rollback() 是否真的会将消息放回队列中。
-
假设我从我的管理员那里获得了这些值,我该如何使用这些值。以及如何在异常上执行会话回滚()?会话对象本身在 onMessage() 方法中是不可访问的。在调试时,我看到消息出现在队列中的那一刻,onMessage() 被触发并且消息从队列中消失
-
谢谢你,当然,请继续写作作为答案。我刚刚检查了队列属性(对我们来说是只读的)并且 Backout Threshold 设置为 1。因此,当抛出异常时,消息的回退计数增加 1。但是如果我减少 BOTHRESH该队列为0,然后在第一次重试时,消息将满足条件“回退计数”> = 0,并且消息将移至回退队列,不是吗?抱歉,我遗漏了一些明显的东西.....
-
增加 BOTHRESH 并添加
使重试成为可能。请把你的建议写在回复里,我会这样标记的。 -
原始问题表明没有观察到回滚。回滚将由
Message Listener中抛出的异常触发。我在DefaultJmsListenerContainerFactory上使用setSessionTransacted(true)进行了测试,并在我的听众声明中添加了throws Exception。在侦听器代码中,您可以检查JMSXDeliveryCount以务实地进行停电,或者按照@Josh 的说明在队列中使用BOTHRESH。
标签: ibm-mq spring-jms