DefaultJmsListenerContainerFactory无法消费IBM MQ大尺寸消息问题排查
我来帮你搞定这个DefaultJmsListenerContainerFactory消费IBM MQ大消息失败的问题!从你贴的报错信息里能看到核心异常是MQRC_TRUNCATED_MSG_FAILED(错误码2080),意思是消息在接收时因为长度超过consumer允许的最大值被截断了。虽然你已经调大了队列的Max Message length,但Default容器的缓存特性让旧的consumer配置被复用,这才是问题根源——而Simple容器因为默认不缓存consumer,每次都会用新配置创建consumer,所以能正常消费大消息。
下面是具体的解决步骤:
1. 给IBM MQ连接工厂设置最大消息长度
首先要确保你的MQ连接工厂明确配置了足够大的最大消息长度,这个值要大于等于你的消息大小(比如7.5MB的话,建议设成8MB,留些余量)。代码示例如下:
import com.ibm.mq.jms.MQConnectionFactory; import com.ibm.msg.client.wmq.WMQConstants; @Bean public MQConnectionFactory mqConnectionFactory() { MQConnectionFactory factory = new MQConnectionFactory(); // 这里填你的MQ基础配置:主机、端口、队列管理器、通道名等 factory.setHostName("your-mq-host"); factory.setPort(1414); factory.setQueueManager("your-queue-manager"); factory.setChannel("your-channel-name"); // 关键配置:设置最大消息长度,单位是字节,8MB=8*1024*1024=8388608 factory.setStringProperty(WMQConstants.WMQ_MAX_MESSAGE_LENGTH, String.valueOf(8388608)); return factory; }
2. 调整DefaultJmsListenerContainerFactory的缓存策略
Default容器默认会缓存MessageConsumer(cacheLevelName默认是CACHE_CONSUMER),如果你的队列最大消息长度是后来修改的,缓存里的旧consumer还是用的原来的小配置。我们可以调整缓存级别,让consumer每次从session重新创建,从而应用新的连接工厂配置:
import org.springframework.jms.config.DefaultJmsListenerContainerFactory; @Bean public DefaultJmsListenerContainerFactory jmsListenerContainerFactory(MQConnectionFactory mqConnectionFactory) { DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory(); factory.setConnectionFactory(mqConnectionFactory); // 把缓存级别改成CACHE_SESSION或CACHE_CONNECTION,避免复用旧的consumer factory.setCacheLevelName("CACHE_SESSION"); // 可选:设置接收超时,给大消息足够的传输时间 factory.setReceiveTimeout(30000); // 30秒,根据你的消息大小调整 return factory; }
3. 检查MQ通道的MAXMSGL配置
别忽略了MQ通道的配置!比如你的SVRCONN通道的MAXMSGL属性也要设置成和队列一致的最大值,不然通道会先截断消息,导致consumer还是拿不到完整的消息。你可以通过MQ Explorer或者runmqsc命令来修改这个属性:
ALTER CHANNEL(CHANNEL_NAME) CHLTYPE(SVRCONN) MAXMSGL(8388608)
最后一步:重启应用
修改完这些配置后,一定要重启你的应用,确保所有缓存的旧consumer都被销毁,新的consumer会用上我们设置的大消息长度配置。
这样调整后,DefaultJmsListenerContainerFactory应该就能正常消费7.5MB的大消息了。
内容的提问来源于stack exchange,提问作者user1665581

