ActiveMQ内存设置和流控
启动脚本设置jvm的内存
if "%ACTIVEMQ_OPTS%" == "" set ACTIVEMQ_OPTS=-Xms1G-Xmx1G -Djava.util.logging.config.file=logging.properties
broker配置中的系统内存和磁盘空间使用量
<systemUsage>
<systemUsage>
<memoryUsage>
<memoryUsagelimit="64 mb"/>
</memoryUsage>
<storeUsage>
<storeUsagelimit="100 gb"/>
</storeUsage>
<tempUsage>
<tempUsagelimit="50 gb"/>
</tempUsage>
</systemUsage>
</systemUsage>
如果是嵌入式(embedded)方式使用的话,可以new一个SystemUsage来添加到BrokerService中去。这里配置的memoryUsage一定要小于jvm中设置的数量。
splitSystemUsageForProducersConsumers导致消费缓慢甚至无法消费的问题
其实broker中还可以单独配置生产者使用的producerSystemUsage 和消费者使用的consumerSystemUsage,格式跟systeUsage一样。
默认情况下,没有配置producerSystemUsage 和 consumerSystemUsage,则生产者和消费者都使用systemUsage。
这时可能会因为生产者线程把内存用完,导致消费者线程处理缓慢甚至无法消费的问题。这种情况下,添加消费端的机器和消费者数量可能都无法增加消费的速度。
解决办法就是:
在broker上设置splitSystemUsageForProducersConsumers=”true”,使得生产者线程和消费者线程各使用各的内存。
默认是 生产者线程内存:消费者线程内存 = 6:4。
也可以通过如下两个参数设置生产者线程内存和消费者线程内存各一半:
producerSystemUsagePortion = 50
consumerSystemUsagePortion = 50
生产者流控
从5.x版本起,可以给每个producer单独设置流控。流控简单的说就是控制生产者的在内存使用限制下的行为。当然,流控的目的在于防止在将ActiveMQ作为内存MQ使用时,生产速度大于消费速度时将MQ撑爆的问题。
分两个情况:
1、 同步发送消息(useAsynSend为false):此时将在SystemUsage的限制下,使用destinationPolicy中的policyEntry中的限制,例如:
<destinationPolicy>
<policyMap>
<policyEntries>
<policyEntry queue="queueA"producerFlowControl="true"memoryLimit="1mb">
<pendingQueuePolicy>
<vmQueueCursor/>
</pendingQueuePolicy>
</policyEntry>
</policyEntries>
</policyMap>
</destinationPolicy>
限制非持久化时queueA 的内存使用量为1mb,达到这个内存使用量时直接阻塞掉producer,直到有空余的内存时,才允许producer发送消息。
也可通过在systemUsage配置上设置sendFailIfNoSpace="true"或 sendFailIfNoSpaceAfterTimeout="3000"来控制客户端异常和等待时间。
异步发送时,由于不阻塞生产者,
可以通过connctionFactory.setProducerWindowSize(1024000);
来控制broker确认收到消息前生产者能发送的最大数据量(字节)。
消费者流控
消费者端,一般来说消费的越快越好,broker的积压越小越好。
但是考虑到事务性和客户端确认的情况,如果一个消费者一次获取到了很多消息却都不确认,这会造成事务上下文变大,broker端这种“半消费状态”的数据变多,所以ActiveMQ有一个prefetchSize参数来控制未确认情况下,最多可以预获取多少条记录。
默认情况如下:
持久化queue:1000条
非持久化queue: 1000条
持久化topic:100条
非持久化topic: 无限制
可以通过3中方式设置prefetchSize
1、 tcp://localhost:61616?jms.prefetchPolicy.all=50
2、 tcp://localhost:61616?jms.prefetchPolicy.queuePrefetch=1
3、 queue = new ActiveMQQueue("TEST.QUEUE?consumer.prefetchSize=10");