活跃的mq消费者数量减少到0

时间:2017-11-14 08:14:31

标签: spring jms activemq

我们面临一个奇怪的问题,其中一些随机队列的activemq消费者正在减少,直到它们变为0,之后它们无法恢复。 一旦发生这种情况,我们必须再次重新部署消费者应用程序以开始处理。 我们一直在努力解决这个问题,但无法找出根本原因。

activemq broker版本5.14.5

以下是连接配置。

<bean id="activeMQIconnectConnectionFactory" class="test.ActiveMQIconnectConnectionFactory">
        <property name="brokerURL" value="failover:(tcp://localhost:61616)"/>
        <property name="prefetchPolicy" ref="prefetchPolicy"/>
        <property name="redeliveryPolicy" ref="redeliveryPolicy"/>
        <property name="trustAllPackages" value="true"/>
        <!-- http://activemq.apache.org/consumer-dispatch-async.html
        The default setting is dispatchAsync=true
         If you want better thoughput and the chances of having a slow consumer are low, you may want to change this to false.
         -->
        <property name="dispatchAsync" value="true"/>
        <!-- 
        whether or not timestamps on messages should be disabled or not. If you disable them it adds a small performance boost.
         Default is false
         -->
        <property name="disableTimeStampsByDefault" value="true"/>

        <!-- http://activemq.apache.org/optimized-acknowledgement.html
        This option is disabled by default but can be used to improve throughput in some circumstances as it decreases load on the broker.
         -->
        <property name="optimizeAcknowledge" value="true"/>
        <!-- Default 300ms
        For us, 5 sec.
         -->
        <property name="optimizeAcknowledgeTimeOut" value="5000"/>
        <property name="useAsyncSend" value="true"/>
        <property name="exceptionListener" ref="jmsExceptionListener"/>
    </bean>

 <bean id="testQueue" class="org.apache.activemq.command.ActiveMQQueue">
        <constructor-arg index="0" value="test.queue"/>
    </bean>

    <bean id="jmsProducerFactoryPool" class="org.apache.activemq.pool.PooledConnectionFactory" destroy-method="stop"
          init-method="start">
        <property name="connectionFactory" ref="activeMQIconnectConnectionFactory"/>
        <property name="maxConnections" value="10"/>
        <property name="maximumActiveSessionPerConnection"
                  value="1000"/>
        <property name="createConnectionOnStartup" value="true"/>
    </bean>

    <bean id="jmsConsumerFactoryPool" class="org.apache.activemq.pool.PooledConnectionFactory" destroy-method="stop"
          init-method="start">
        <property name="connectionFactory" ref="activeMQIconnectConnectionFactory"/>
        <property name="maxConnections" value="10"/>
        <property name="maximumActiveSessionPerConnection"               value="1000"/>
        <property name="createConnectionOnStartup" value="true"/>
        <property name="reconnectOnException" value="true"/>
        <property name="idleTimeout" value="86400000"/>
    </bean>

    <bean id="redeliveryPolicy" class="org.apache.activemq.RedeliveryPolicy">
        <property name="maximumRedeliveries" value="1"/>
        <property name="queue" value="*"/>
    </bean>

    <bean id="prefetchPolicy" class="org.apache.activemq.ActiveMQPrefetchPolicy">
        <property name="queuePrefetch" value="500"/>
    </bean>

    <bean id="jmsTemplate" class="com.minda.iconnect.jms.impl.TimedJmsTemplate">
        <property name="connectionFactory" ref="jmsProducerFactoryPool"/>
        <property name="defaultDestinationName" value="iconnect.queue"/>
        <property name="deliveryPersistent" value="true"/>
        <!-- I think this is ingored if explicitQosEnabled is not set -->
    </bean>

    <bean id="simpleMessageConverter" class="org.springframework.jms.support.converter.SimpleMessageConverter"/>

<bean id="testProducer"
          class="com.test.TestProducer">
        <property name="consumerDestination" ref="testQueu"/>
        <property name="jmsTemplate" ref="jmsTemplate"/>
        <property name="messageConverter" ref="simpleMessageConverter"/>
    </bean>

    <bean id="testContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
        <property name="connectionFactory" ref="jmsConsumerFactoryPool"/>
        <property name="destination" ref="testS"/>
        <property name="messageListener">
            <bean class="org.springframework.jms.listener.adapter.MessageListenerAdapter">
                <property name="delegate" ref="testConsumer"/>
                <property name="defaultListenerMethod" value="process"/>
                <property name="messageConverter" ref="simpleMessageConverter"/>
            </bean>
        </property>
        <property name="concurrentConsumers" value="50"/>
        <property name="maxConcurrentConsumers" value="100"/>
        <property name="sessionTransacted" value="false"/>
        <property name="autoStartup" value="true"/>
    </bean>
</beans>

connectionFactory的类

public class ActiveMQIconnectConnectionFactory extends org.apache.activemq.ActiveMQConnectionFactory
{
    private static final Logger LOG = LoggerFactory.getLogger(ActiveMQIconnectConnectionFactory.class);

    @Override
    public void setBrokerURL(String brokerURL)
    {
        // LOG when connecting to activemq
        // using this setter to be sure it's only logged once
        // See DJ-5780
        LOG.info("ActiveMQ configured is: " + (DEFAULT_BROKER_URL.equals(brokerURL) ? "(default init setting) " : "") + brokerURL);
        LOG.info("Connecting to ActiveMQ");
        super.setBrokerURL(brokerURL);
    }
}

直到现在我们一直在玩超时等参数但不是运气。 我们怀疑问题是由于某些连接问题或通过DMLC处理连接而发生的,但无法识别问题。非常感谢帮助!

1 个答案:

答案 0 :(得分:0)

我认为您的问题是基于您的配置相互影响的Spring DMLC和AMQ行为的混合。

尝试更改:

<property name="optimizeAcknowledgeTimeOut" value="500"/>

org.springframework.jms.listener.DefaultMessageListenerContainer.setReceiveTimeout(0);

org.springframework.jms.listener.DefaultMessageListenerContainer.setReceiveTimeout(10000);
org.springframework.jms.listener.DefaultMessageListenerContainer.setIdleTaskExecutionLimit(100);

https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/jms/listener/AbstractPollingMessageListenerContainer.html#setReceiveTimeout-long-

https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/jms/listener/DefaultMessageListenerContainer.html#setIdleTaskExecutionLimit-int-

  

public void setIdleTaskExecutionLimit(int   idleTaskExecutionLimit)指定a的空闲执行限制   消费者任务,在其执行过程中没有收到任何消息。   如果达到此限制,任务将关闭并离开接收   到其他执行任务。默认值为1,关闭空闲资源   一旦任务没有收到消息就提前。这适用于动态   只安排;看&#34; maxConcurrentConsumers&#34;设置。最低   消费者的数量(见&#34;并发消费者&#34;)将被保留   直到任何情况下关闭。

     

在每个任务执行期间,进行多次消息接收尝试   (根据&#34; maxMessagesPerTask&#34;设置)将等待一个   传入消息(根据&#34; receiveTimeout&#34;设置)。我摔倒   那些在没有消息的特定任务返回中接收尝试的人,   对于接收的消息,该任务被认为是空闲的。这样的   任务仍可以重新安排;但是,一旦达到指定的   &#34; idleTaskExecutionLimit&#34;,它将关闭(如果是动态的话   缩放)。

     

如果您遇到过于频繁的放大和缩小,请提高此限制。   随着这个限制越来越高,闲置的消费者将被保留   更长的时间,一旦新的消息加载,就避免重新启动消费者   或者,指定一个更高的&#34; maxMessagesPerTask&#34;和/或   &#34; receiveTimeout&#34;价值,这也将导致闲置的消费者   保持较长时间(同时也增加了平均值)   每个计划任务的执行时间。)

http://activemq.apache.org/performance-tuning.html

  

优化确认在自动确认模式下使用消息时   (在创建消费者&#39;会话时设置),ActiveMQ可以确认   收到批量回邮件的消息(改进   性能)。 批量大小是预取限制的65%   消费者。此外,如果消息消耗很慢,则将发送批次   每300毫秒。您可以通过设置切换批量确认   ActiveMQ ConnectionFactory上的optimizeAcknowledge = true。

http://activemq.apache.org/what-is-the-prefetch-limit-for.html

  

一旦代理发送了预取限制数量的消息   消费者它不会向该消费者发送任何更多消息   直到消费者承认至少50%的预取   消息,例如prefetch / 2,它收到的消息。当经纪人有   收到上述确认后,它将发出进一步的预取/ 2   向消费者提供的消息数量,以及其自身的充值信息   预取缓冲区。请注意,可以指定预取限制   基于每个消费者(见下文)。