如何通过DefaultJmsListenerContainerFactory减少IBM MQ空get调用
针对你遇到的IBM MQ空获取(MQ get without data)过多的问题,结合当前配置和业务场景,可通过以下配置调整来减少空请求:
缩短
receiveTimeout接收超时时间
当前配置的120000L(2分钟)超时过长,无消息时消费者会阻塞到超时才返回空获取,随后立即发起下一轮请求。建议将超时调整为1000ms(1秒),既避免长时间阻塞,又不会因超时过短导致频繁轮询:factory.setReceiveTimeout(1000L);配置IBM MQ专属的等待参数
如果你的defaultJmsConnectionFactory是IBM MQ的MQConnectionFactory,可直接设置服务器端等待参数,让MQ服务器在无消息时持有请求,直到有消息或超时再返回,减少客户端空轮询:MQConnectionFactory mqConnFactory = (MQConnectionFactory) defaultJmsConnectionFactory; mqConnFactory.setWaitInterval(500); // 服务器侧等待消息的间隔(毫秒) mqConnFactory.setMaxWait(1000); // 最大等待时长(毫秒)保持消费者与队列的1:1对应
当前每个@JmsListener的并发设置为1-1,刚好4个队列对应4个消费者,与线程池核心线程数匹配。之前增加并发导致空请求增多,是因为同一队列多消费者竞争无消息的队列,建议维持当前concurrency="1-1"的配置,避免同一队列多消费者空轮询。移除退避策略配置
当前的FixedBackOff配置是针对连接失败的重试逻辑,但在无消息的正常场景下,会导致消费者空获取后主动重试,增加空请求次数。建议删除以下配置:// factory.setBackOff(new FixedBackOff(40*1000, 3));切换到SIMPLE消息监听容器
DefaultJmsListenerContainerFactory默认使用DefaultMessageListenerContainer,循环获取消息的模式容易产生空请求。可切换为SimpleMessageListenerContainer,它采用阻塞式获取逻辑,无消息时会持续阻塞直到有消息,减少空获取:factory.setContainerType(DefaultJmsListenerContainerFactory.ContainerType.SIMPLE);优化线程池配置
当前线程池最大线程数设为6,但你的消费者固定为4个,不会触发线程扩容。建议将最大线程数调整为4,避免线程池不必要的扩容开销:taskExecutor.setMaxPoolSize(4);
内容的提问来源于stack exchange,提问作者Chetan

