首页 > 解决方案 > Spring Message Listener - 连接刷新

问题描述

我们已经用 spring 实现了一个消息监听器,容器配置如下所示

    <bean id="customContainer"
        class="org.springframework.jms.listener.DefaultMessageListenerContainer">
        <property name="concurrentConsumers" value="${jms.customContainer.concurrentconsumers}" />
        <property name="maxConcurrentConsumers" value="${jms.customContainer.maxconcurrentconsumers}" />
        <property name="errorHandler" ref="errorHandler" />
        <property name="connectionFactory" ref="jmsQueueConnectionFactory" />
        <property name="destination" ref="listenerQueue" />
        <property name="messageListener" ref="customContainerListener" />
        <property name="receiveTimeout" value="1" />
        <property name="sessionTransacted" value="true" />
        <property name="transactionManager" ref="txManager" />
    </bean>

它部署在 Jboss 和服务器日志中经常显示以下连接刷新消息。

org.springframework.jms.listener.DefaultMessageListenerContainer] (customContainer-3849) Successfully refreshed JMS Connection

据报道,托管 WebSphere MQ 的大型机端的 MSU/MIPS 利用率很高。这可能是导致频繁 MQ GET 调用和提高利用率的原因吗?

我们没有明确指定消息回复到,这会导致回复每次都尝试排队吗?接收超时也设置为 1 毫秒,这是否意味着它将每 1 毫秒主动轮询一次队列?有人可以解释一下这个概念吗?

标签: springjbossjmsibm-mq

解决方案


DefaultMessageListenerContainer实现队列的轮询。这意味着它发出一个 GET 等待receiveTimeout. 如果您有receiveTimeout1ms 的时间,这意味着如果队列中没有消息并且将进行另一个 GET 调用,则每个 GET 调用将在 1ms 后返回。这对于队列管理器来说是背靠背的 GET 调用。

两种选择:

  1. 您可以增加receiveTimeout一个更高的数字,这将导致指定值的等待获取,例如,等待 60000 毫秒的获取只会每 1 分钟或在消息到达队列后执行一次获取。一旦将消息放入队列,您仍然可以从队列中获取消息。
  2. 如果可能,一个更有效的选择是切换到SimpleMessageListenerContainer将使用本机 JMS 异步侦听器的选项。对于 IBM MQ,这是通过 MQ 回调功能实现的。这意味着侦听器向队列管理器注册回调,并且队列管理器在新消息到达队列时通知侦听器,因此没有轮询。

推荐阅读