这里所谓的优化,是基于使用 mqtt 协议和 topic 订阅发布模式为案例展开,尽量简化到最少资源开销;
1. 启动连接参数
打开 \conf\activemq.xml 配置文件,对 transportConnectors 节点进行配置,如下:
1 <transportConnectors>
2 <!-- DOS protection, limit concurrent connections to 1000 and frame size to 100MB -->
3 <!-- <transportConnector name="openwire" uri="tcp://0.0.0.0:61616?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>-->
4 <!-- <transportConnector name="amqp" uri="amqp://0.0.0.0:5672?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>-->
5 <!-- <transportConnector name="stomp" uri="stomp://0.0.0.0:61613?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>-->
6 <transportConnector name="mqtt" uri="mqtt://0.0.0.0:1883?maximumConnections=1000&wireFormat.maxFrameSize=104857600&transport.defaultKeepAlive=90000&allowLinkStealing=false&transport.activeMQSubscriptionPrefetch=1000&wireFormat.maxInactivityDuration=30000&wireFormat.maxInactivityDurationInitalDelay=10000&transport.useInactivityMonitor=true&transport.useKeepAlive=true"/>
7 <!-- <transportConnector name="ws" uri="ws://0.0.0.0:61614?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>-->
8 </transportConnectors>
View Code
maximumConnections=1000&wireFormat.maxFrameSize=104857600 : 为了防止 DOS 攻击,限制了并发连接数及最大并发传输容量(最大容量: 256MB);
transport.defaultKeepAlive=90000 : 配置服务器的默认心跳;默认值为:假设客户端心跳时间为 10秒,服务端对该连接的检测时间则为:10*1.5=15秒;
此处配置为 90秒,则客户端心跳建议为:60秒(配置看场景需求而定);
allowLinkStealing=false :如果有两个或以上的连接使用了相同的 CilentID,则视为盗链;服务器将丢弃后来者的连接(从日志可以看到以下信息)
WARN | Stealing link for clientId PUBSameID-001 From Connection
transport.activeMQSubscriptionPrefetch=100: 如果订阅端的处理能力较强,消息较小; 这个值越大越好,即服务端将预推多少消息量给订阅端,然后等订阅端 ACK后再推;
这个设置需要评估订阅端的最低处理能力,并根据服务器性能来配置;
wireFormat.maxInactivityDuration=90000: 如果服务器在 90s 内没有接收到某个连接发来的消息,则自动断开该连接;
transport.useKeepAlive=true: 如果设置为 false,则服务器在心跳时间外没收到数据也不会强制关闭连接;
wireFormat.maxInactivityDurationInitalDelay=10000:指定 "不活动链接监视器 (InactivityMonitor)" 在服务启动后多长时间后启动,在需要并发创建许多连接场景非常能有效的降低服务器开销;
transport.useInactivityMonitor=true: 启用”不活动链接监视器“,如果设置为 false,则服务器不监控”不活动连接“;
2. 预存消息量
这里还需要关注 constantPendingMessageLimitStrategy 配置,与 Prefetch Size 相关;
慢消费者会在非持久的topics上导致问题:一旦消息积压起来,会导致broker把大量消息保存在内存中,broker也会因此而变慢。
可以通过配置缓存消息的上限,超过这个上限后,新消息到来时会丢弃旧消息;
如下配置,或者 使用倍数方式代替消息条数:<prefetchRatePendingMessageLimitStrategy multiplier="2.5"/>
1 <destinationPolicy>
2 <policyMap>
3 <policyEntries>
4 <policyEntry topic=">" >
5 <pendingMessageLimitStrategy>
6 <constantPendingMessageLimitStrategy limit="1000"/>
7 </pendingMessageLimitStrategy>
8 </policyEntry>
9 </policyEntries>
10 </policyMap>
11 </destinationPolicy>
View Code
3. 数据清理
A)消息主题 / 队列清理:在规定的时间内,如果无有效订阅,没有入队消息,超时后就会被清理;
配置包含以下三个值;
schedulePeriodForDestinationPurge : 在 broker 上设置任务清理周期(毫秒);
gcInactiveDestinations : 在策略上配置是否启用Topic(或queue)清理任务;
inactiveTimoutBeforeGC :Topic(queue)清理间隔周期(毫秒)
1 <broker schedulePeriodForDestinationPurge="86400000">
2 <destinationPolicy>
3 <policyMap>
4 <policyEntries>
5 <policyEntry topic=">" gcInactiveDestinations="true" inactiveTimoutBeforeGC="43200000" ></policyEntry>
6 <policyEntry queue=">" gcInactiveDestinations="true" inactiveTimoutBeforeGC="43200000" ></policyEntry>
7 </policyEntries>
8 </policyMap>
9 </destinationPolicy>
10 </broker>
View Code
4. 内存与磁盘空间
对 ActiveMQ 的使用空间策略配置;
memoryUsage :ActiveMQ使用的内存(可用的百分比),必须大于或等于 destinationPolicy 中设置的所有队列的内存之和;
storeUsage :持久化存储文件的大小;
tempUsage :非持久化消息存储的临时内存大小;
1 <broker>
2 <systemUsage>
3 <systemUsage>
4 <memoryUsage>
5 <memoryUsage percentOfJvmHeap="70" />
6 </memoryUsage>
7 <storeUsage>
8 <storeUsage limit="100 gb"/>
9 </storeUsage>
10 <tempUsage>
11 <tempUsage limit="50 gb"/>
12 </tempUsage>
13 </systemUsage>
14 </systemUsage>
15 </broker>
View Code