【发布时间】:2021-10-02 11:55:11
【问题描述】:
我正在使用 Spring @JmsListener 来使用来自 IBM MQ 队列的消息(在 Docker 容器中运行)。我测试一个场景如下:
- 通过网络浏览器向 MQ 发送消息
- 我的 Spring 服务将使用从消息中提取的数据并将其发送到存根 (wiremock)
- 服务收到成功响应并正常退出
在一个愉快的情况下,消息将被提交并从队列中删除,现在我在存根中添加响应延迟(例如 30 秒),当服务等待响应时,我退出 Docker 以模拟网络问题或 MQ 关闭(docker停止导致 MQ 停顿,这不是我的预期)。
所以我这里有 2 个问题?
- 如何捕捉 DefaultMessageListenerContainer 抛出的提交异常?
- 我使用 DefaultJmsListenerContainerFactory::setExceptionListener() 方法来附加一个监听器,我可以在此处记录异常,但不会记录 logback MDC(MDC 包含用于审计目的的 messageId 和有效负载)。如何将 MDC 值传递给此侦听器?
源代码:
@Bean
public DefaultJmsListenerContainerFactory containerFactory() {
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
factory.setConnectionFactory(createConnectionFactory());
factory.setExceptionListener(exceptionListener());
factory.setSessionAcknowledgeMode(javax.jms.Session.CLIENT_ACKNOWLEDGE);
return factory;
}
@Bean
public ExceptionListener exceptionListener() {
return exception -> {
if (exception.getCause() instanceof InterruptedException) {
// MDC value is not logged in below log.error()
log.error("commit error");
} else {
log.error("jms connection error");
}
}
}
---
@JmsListener(id="0", destination="DEV.QUEUE.1", containerFactory="containerFactory")
public void listener(Message msg) {
try {
// extract data
MDC.put("key", value); // for audit
// call stub
} catch (JMSException e) {
throw new Exception(e); // throw exception, don't commit
}
}
任何帮助将不胜感激。
【问题讨论】:
-
我没有看到任何设置事务的代码,或消息获取和提交之间的延迟,或提交。
-
@daury 如果您在 MQ 队列管理器 docker 实例上运行
docker stop,那么您的队列管理器将停止。如果您终止该过程,那么它将终止。您可以使用docker network disconnect来模拟各种容器之间的网络中断吗?您看到正在处理的消息的JMSXDeliveryCount增加了吗? -
@chughts 我这里没有设置事务,如果监听器正常返回无异常,则消息被提交并从队列中移除,否则将被移动到DLQ - 此行为在IBM MQ中配置.
-
@richc
JMSXDeliveryCount收到消息时为1,断开连接后仍为1,但运行docker network disconnect时我的服务没有抛出异常 -
当我运行
dis qs(DEV.QUEUE.1)时,它返回 UNCOM(1),但过了一会儿,它返回 UNCOM(NO)
标签: jms ibm-mq spring-jms