尽管producerFlowControl为false,但activemq缓慢消费者阻止生产者

时间:2013-10-31 21:02:04

标签: jms activemq

我的系统中使用了activemq,我看到的是以下消息: TopicSubscription:consumer = ...:Pending message cursor [org.apache.activemq.broker.region.cursors.VMPendingMessageCursor@1684f89c]已满,临时使用率(0%)或内存使用率(100%)达到限制,阻止消息添加()等待资源的发布。

这是因为如果我理解正确,我的消费者很慢,而我的制作人很快。结果是最终我的生产者被阻止,直到消费者读取消息并释放一些内存。我想知道的是我的制作人没有被封锁,而且当内存已经完整时,旧的消息也被发现了。

鉴于我对所读内容的理解,下面的配置应该可以解决这个问题(messageEvictionStrategy,pendingMessageLimitStrategy),但它对我不起作用,我无法弄明白为什么。

由于测试原因,我已指定低内存限制低(35Mb)以使问题更快,但情况是我最终需要它,当activemq出现问题时,只需丢弃旧消息。

我在ActiveMQConnectionFactory中找到了一个非常令人满意的解决方案,使用了asyncSend = true并指定了sendTimeout。这使得生产者没有被阻止,但是这样就删除了最新的消息而不是olderst消息。

最后,我正在谈论非持久性主题。

任何帮助人员都会完美。下面我有activemq配置

        <destinationPolicy>
        <policyMap>
            <policyEntries>
                <policyEntry topic=">" producerFlowControl="false" memoryLimit="35 Mb">
               <pendingSubscriberPolicy>
                   <vmCursor />
                </pendingSubscriberPolicy>
                    <messageEvictionStrategy>
                        <oldestMessageEvictionStrategy/>
                    </messageEvictionStrategy>
                    <pendingMessageLimitStrategy>
                        <constantPendingMessageLimitStrategy limit="10"/>
                    </pendingMessageLimitStrategy>
                </policyEntry>
            </policyEntries>
        </policyMap>
    </destinationPolicy>

    <systemUsage>
        <systemUsage sendFailIfNoSpace="true">
            <memoryUsage>
                <memoryUsage limit="35 mb"/>
            </memoryUsage>
            <storeUsage>
                <storeUsage limit="1 gb"/>
            </storeUsage>
            <tempUsage>
                <tempUsage limit="5000 mb"/>
            </tempUsage>
        </systemUsage>
    </systemUsage>  

activemq版本5.7.0

我使用spring模板发送消息:

    <bean class="org.springframework.jms.core.JmsTemplate">
    <property name="connectionFactory" ref="pooledJmsConnectionFactory"/>
    <property name="timeToLive" value="100"/>
</bean>

我传输的javax.jms.ObjectMessage相对较小。

我在客户前提中发现了问题我在我的应用程序中有很多toppics但是设法重现它从1个线程,不间断的消息始终发送到同一主题的本地发送。消息发送只是一个小字符串。

我只有一个生产者,当我有一个(或更多)慢的消费者时似乎出现问题 - 但是一个慢的消费者就足够了。如果不存在缓慢的消费者,则不会出现问题。

我不认为它有任何区别,但我使用

       <transportConnectors>
       <transportConnector name="openwire" uri="nio://0.0.0.0:33029?wireFormat.maxInactivityDuration=60000&amp;wireFormat.maxInactivityDurationInitalDelay=60000"/>
    </transportConnectors>

2 个答案:

答案 0 :(得分:2)

我该如何重新创建?这个主题有多少生产者/消费者?这只是一个话题吗?

您的设置看起来没问题,但您不需要在策略上设置memoryLimit = 35mb。将它设置为与整个系统使用相同是没有意义的。这个想法是所有主题的内存限制组合将等于系统内存限制。例如,如果您有两个主题,每个主题将使用35MB(2 * 35 == 70MB),这将超过整个系统内存设置。我不认为这是你所看到的具体原因,但要记住一些事情。

这是什么版本的ActiveMQ?如果您已经编写了一些可以产生此功能的测试,请告诉我们。

答案 1 :(得分:1)

事实证明,当使用JmsTemplate以便发送异步然后发送无法传递的消息时,我们需要启用explicitQosEnabled并设置deliveryMode = 1(非持久性)。 同样在客户端,消费者需要具有较小的预取限制

服务器

<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
    <property name="connectionFactory" ref="pooledJmsConnectionFactory"/>
    <property name="explicitQosEnabled" value="true"/>
    <property name="deliveryMode" value="1"/>
</bean>

客户

<jms:listener-container .. prefetch="1000">
...
</jms:listener-container>

不要问我为什么......但这似乎解决了我的问题。 基本上非100%需要,但如果有人可以向我解释这将是完美的

相关问题