JmsTemplate特设消费者正在挨饿

时间:2014-12-09 12:26:53

标签: java spring jms activemq jmstemplate

我试图为我的JMS消息创建一个临时使用者(我使用ActiveMQ)

它看起来像这样:

 jmsTemplate.browse(
                          q.getName(),
                          new BrowserCallback<Integer>() {

                          @Override
                          public Integer doInJms(Session session, QueueBrowser browser) throws JMSException {

                              Queue destination = session.createQueue(q.getName());
                              Enumeration<?> enum1 = browser.getEnumeration();

                              while (enum1.hasMoreElements()) {
                              ActiveMQObjectMessage msg = (ActiveMQObjectMessage) enum1.nextElement();
                              MessageConsumer consumer = session.createConsumer(destination);
                              Message m = consumer.receiveNoWait();
                              handle(m);
                              m.acknowledge();

此临时使用者应处理所有未能使用的消息。 问题是我在spring-messaging.xml中定义的原始2-3个消费者不断尝试通过重新传递配置来处理失败的事件和重试(重新传递延迟设置为3秒,并且重新传输的数量是无限的)

这位消费者应该处理这些消息,但实际上是在挨饿(根本不会收到这些消息,因此

          Message m = consumer.receiveNoWait();

始终返回null。

这是我的豆子:

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

    <!-- A JmsTemplate instance that uses the cached connection and destination -->
<bean id="redeliveryJmsTemplate" class="org.springframework.jms.core.JmsTemplate">
    <property name="connectionFactory" ref="redeliveryCachingConnectionFactory" />
    <property name="messageConverter" ref="eventConverter" />
    <property name="sessionTransacted" value="true" />
</bean>

p.s当我将p:sessionCacheSize的配置更改为1:

    <bean id="redeliveryCachingConnectionFactory"
    class="org.springframework.jms.connection.CachingConnectionFactory"
    p:targetConnectionFactory-ref="redeliveryConnectionFactory"
    p:sessionCacheSize="1" />

它有效,但我想使用缓存。

有什么想法吗?

1 个答案:

答案 0 :(得分:0)

您假设队列浏览器正在返回耗材消息。浏览消息就像是浏览完成时的快照。它将包括分配给预取的任何消息,或者当您再次访问它时,它可能已被消耗。此外,您不会等待分配消息,因此您不断回到消息行。

我建议允许将消息移动到DLQ,然后允许此Adhoc消费者使用它。否则,您正在与其他消费者竞争消息。

如果您真的死于使用DLQ,则可以使用JMS selectors基于JMSRedelivered标头为true,等待时间更长。您仍然会与其他消费者竞争,但会在某个时候收到消息。