Camel ActiveMQ 客户端阻塞,临时存储使用率立即达到 100%

Posted

技术标签:

【中文标题】Camel ActiveMQ 客户端阻塞,临时存储使用率立即达到 100%【英文标题】:Camel ActiveMQ client blocking, temp storage usage immediately hits 100% 【发布时间】:2015-10-19 05:43:58 【问题描述】:

我看到 activemq 的临时存储(配置为 100mb)的利用率为 100%,并且 activemq 客户端正在阻塞。这种 100% 的使用会永久保持,我不知道发生了什么

我有一条骆驼路线,它使用 JmsTransactionManager 从队列 (QUEUE.IN) 中消费。

public final class RouteUnderTest extends RouteBuilder 

    @Override
    public void configure() throws Exception 
        from("activemq-transacted:QUEUE.IN")
                .bean(myBean)
                .to("activemq:QUEUE.OUT");
    

在处理来自该队列的消息时,我正在调用一个 spring-integration 客户端 (myBean),其配置如下

<int:gateway id="myBean" service-interface="MyBean">
    <int:method name="request" request-channel="channel"/>
</int:gateway>

<int:chain input-channel="channel">
    <int:transformer ref="transformedToJsonHere"/>
    <jms:outbound-gateway request-destination-name="QUEUE.MYBEAN"
                          receive-timeout="5000"
                          explicit-qos-enabled="true"
                          time-to-live="5000"
                          delivery-persistent="false"/>
    <int:transformer ref="transformedToAnObjectHere"/>
</int:chain>

我的代理配置为使用 LevelDB,并具有以下使用限制:

<persistenceAdapter>
    <levelDB directory="$activemq.data/leveldb"/>
</persistenceAdapter>

<systemUsage>
    <systemUsage>
        <memoryUsage>
            <memoryUsage percentOfJvmHeap="70"/>
        </memoryUsage>
        <storeUsage>
            <storeUsage limit="500 mb"/>
        </storeUsage>
        <tempUsage>
            <tempUsage limit="100 mb"/>
        </tempUsage>
    </systemUsage>
</systemUsage>

当我的路由使用消息,然后尝试在 QUEUE.OUT 上放置非持久性消息时,客户端被阻止并且我的代理显示 100% 的临时存储使用率。

我看到了以下 activemq 日志

2015-07-28 15:44:59,678 | INFO  | Usage(default:temp:queue://QUEUE.MYBEAN:temp) percentUsage=0%, usage=104857600, limit=104857600, percentUsageMinDelta=1%;Parent:Usage(default:temp) percentUsage=100%, usage=104857600, limit=104857600, percentUsageMinDelta=1%: Temp Store is Full (0% of 104857600). Stopping producer (ID:orbit-vm-55561-1438094698190-1:1:3:1) to prevent flooding queue://QUEUE.MYBEAN. See http://activemq.apache.org/producer-flow-control.html for more info (blocking for: 1s) | org.apache.activemq.broker.region.Queue | ActiveMQ NIO Worker 6

队列看起来像(您可以看到 QUEUE.IN 消息尚未出队,因为它仍在事务处理中,并且没有消息发送到 QUEUE.MYBEAN)

我可以使用以下任何一种方法来解决此问题:

    使用 KahaDB 代替 LevelDB 增加临时存储限制(150MB 似乎可以,但我没有进行大量实验) 在 activemq.xml 中配置 tempDataStore(见下文)

配置 tempDataStore 时如下所示:

<tempDataStore> 
    <bean xmlns="http://www.springframework.org/schema/beans" class="org.apache.activemq.leveldb.LevelDBStore"> 
        <property name="directory" value="$activemq.data/tmp" /> 
    </bean> 
</tempDataStore> 

我应该补充一下,我们之前使用的是 KahaDB,并且效果很好,但是升级到 LevelDB 后就暴露了这个问题。恢复到 KahaDB 不是一种选择。

我希望有人能解释一下我们在这里看到的情况,因为结果真的很难理解。为什么使用 LevelDB 需要更高的临时使用限制?为什么显式配置 tempDataStore 也可以解决问题?

我不完全理解这里发生了什么,所以我担心只是稍微增加临时使用限制只会在以后隐藏问题。

版本:

ActiveMQ:5.11.1 骆驼:2.14.0 春季:4.0.8.RELEASE Spring 集成:4.0.5.RELEASE

【问题讨论】:

【参考方案1】:

我们在 ActiveMQ 5.13.2 中遇到了完全相同的问题

使用 LevelDB 时的解决方案是像您一样显式配置一个专用的tempDataStore

如果不是,代理对持久(持久使用)和非持久消息(临时使用)使用相同的存储 (LevelDB)。因此,您可能会在代理不再接受任何非持久消息的情况下结束,因为存储已经将持久消息保持在配置的tempUsage 限制。但是,如果您的 storeUsage 限制设置得更高,它将接受持久性...

使用 KahaDB 时,代理会自动使用另一个存储来存储非持久性消息(在 tmp 目录中创建)。所以你没有问题...

查看以下代码以获得更深入的信息:https://github.com/apache/activemq/blob/activemq-5.13.2/activemq-broker/src/main/java/org/apache/activemq/broker/BrokerService.java#L1739

阅读该代码时,请记住 LevelDBStore 实现了 PListStore,但 KahaDBStore 没有...

【讨论】:

以上是关于Camel ActiveMQ 客户端阻塞,临时存储使用率立即达到 100%的主要内容,如果未能解决你的问题,请参考以下文章

用 Camel 拦截 ActiveMQ 消息

Camel ActiveMQ 性能调优

Camel ActiveMQ + Spring boot 不读取 spring activemq 配置

Spring、Camel、ActiveMQ 和 WebSockets

带有 ActiveMQ 集群的 Apache Camel

使用 ActiveMQ、Camel 和 Spring 实现请求-回复模式