Spring JmsTemplate的receiveTimeout配置未生效问题求助
大家好,我最近在做基于Spring的应用连接IBM MQ收发JMS消息的功能,遇到了一个棘手的问题:我通过JmsTemplate的setReceiveTimeout方法配置了接收超时时间,原本预期超时后会抛出JmsException,但实际应用会一直等待,直到响应队列返回消息才会继续执行。我试过把超时值从100毫秒调到10000毫秒,都没有效果,代码里计算的实际等待时长总是超过我配置的receiveTimeout值。
我是按照Spring官方文档的说明来设置的,文档里对这个方法的描述是:
Set the timeout to use for receive calls (in milliseconds). The default is
JmsDestinationAccessor.RECEIVE_TIMEOUT_INDEFINITE_WAIT, which
indicates a blocking receive without timeout.
为了排查问题,我开启了MQ客户端的跟踪日志,确认配置的超时值确实被正确设置了(比如我设500毫秒时,日志输出如下):
System.setProperty("com.ibm.msg.client.commonservices.trace.status","ON");
对应的日志片段(mqjavaclient_4909.tc):
00000002 @c1d1ad5 c.i.m.c.j.wmq.internal.WMQGMO(MQGMO)----+----+-d getWaitInterval() getter [500(0x1f4)]
下面是我的相关配置和代码:
- IBM MQ客户端依赖版本:
<dependency> <groupId>com.ibm.mq</groupId> <artifactId>mq-jms-spring-boot-starter</artifactId> <version>3.2.4</version> </dependency>
- JmsTemplate Bean定义:
@Bean public JmsTemplate jmsTemplate() throws JMSException { var mqQueueConnectionFactory = mqQueueConnectionFactory(); var userCredentialsConnectionFactoryAdapter = getUserCredentialsConnectionFactoryAdapter(mqQueueConnectionFactory); var jmsTemplate = new JmsTemplate(userCredentialsConnectionFactoryAdapter); jmsTemplate.setReceiveTimeout(Long.parseLong(receiveTimeout)); return jmsTemplate; }
- 实际调用代码:
System.out.println(start); var message = (TextMessage) jmsTemplate.sendAndReceive(destinationMq, session -> { TextMessage textMessage = session.createTextMessage(mqRequest.request()); textMessage.setJMSCorrelationID(mqRequest.correlationId()); textMessage.setJMSReplyTo(getMQ(mqRequest.replyToQueue())); return textMessage; }); System.out.println(System.currentTimeMillis() - start);
Update 1:临时解决方案
暂时没找到根本原因,我换了一种方式实现超时:把sendAndReceive的调用封装成Future任务,用ExecutorService的get(timeout, unit)方法来控制超时,这个方法能正常生效。更新后的代码如下:
Future<TextMessage> responseFuture = mqExecutorService.submit(() -> (TextMessage) jmsTemplate.sendAndReceive(destinationMq, session -> { TextMessage textMessage = session.createTextMessage(mqRequest.request()); textMessage.setJMSCorrelationID(mqRequest.correlationId()); textMessage.setJMSReplyTo(getMQ(mqRequest.replyToQueue())); return textMessage; })); try { TextMessage message = responseFuture.get(Long.parseLong(responseTimeout), TimeUnit.MILLISECONDS); } catch (Exception ex) { responseFuture.cancel(true); }
有没有大佬遇到过类似的问题?或者能指点下为什么receiveTimeout不生效吗?
备注:内容来源于stack exchange,提问作者dope

