如何消息队列的数据积压问题( 二 )


4.3.3 优化ActiveMQ的queuePrefetch 参数预获取消息数量是MQ中重要的调优参数之一 , 为了提高网络的传输效率 , ActiveMQ默认给Consumer批量push 1000条消息 , 可以从ActiveMQ源码中的ActiveMQPrefetchPolicy类的DEFAULT_QUEUE_PREFETCH字段得知 , 考虑到我们的通知消息的消费处理中涉及到数据库的操作 , 以及综合网络传输效率 , 这里将queuePrefetch的值设置为100 , 具体需配置到ActiveMQ的连接地址后 , 如:
tcp://localhost:61616?jms.prefetchPolicy.queuePrefetch=1004.3.4 优化queuePrefetch参数后的性能测试
测试次数 是否并发处理 消息数量
queuePrefetch
consumers 耗时
1 是 15000 100 40 7s2 是 15000 100 47 5s3 是 15000 100 41 6s将ActiveMQ的queuePrefetch参数修改为100 , 那么发现有近一半的消费者在处理数据 , 最后15000条消息需要6s中就可以处理完成 。
4.3.5 结论通过以上两步的优化后的测试结果可以得出 , 取消同步锁之后队列的消费能力提升了近11倍 , 在取消同步锁的基础上再优化ActiveMQ批处理参数后性能又提升了近1倍 , 综合以上两步的优化处理 , 队列整体的消费能力提高了30多倍 。

如何消息队列的数据积压问题

文章插图
 
5 阶段二优化方案阶段二的优化方案是在阶段一的基础上进行的优化处理
5.1 单队列处理
如何消息队列的数据积压问题

文章插图
由于我们的消息通知业务属于幂等性操作 , 会按照设定的通知次数来反复通知处理 , 直到通知成功为止 , 我们系统现在的做法是将接收到MQ的消息暂存于延时队列(DelayQueue)中 , 然后通过多线程轮训取出 , 然后通过HTTP通知到其他模块处理 , 如果通知失败 , 则重新放入同一个延时队列等待下次执行 , 如上图:消息1通知失败后会重新放入延时队列 。
注:单队列处理的不足
由于使用了单队列处理 , 使得可以一次通知成功的消息与通知多次失败的消息混合在了一起 , 这样在队列中失败通知的消息就会阻塞到后续可以正常通知的消息 , 最终导致消息整体的一个吞吐量下降
5.2 双队列处理
如何消息队列的数据积压问题

文章插图
针对5.1单队列的不足 , 我们可以重新设计 , 将单队列设计为双队列处理 , 双队列的核心思想为如果队列1中的消息通知失败 , 则不再重新放入队列1 , 而是放入队列2去通知 , 这样可以起到消息数据分离的作用 , 及失败通知的数据不再会影响到后续可以成功通知的消息 , 从而提高队列消息通知的整体性能!
 
6 阶段三优化方案【如何消息队列的数据积压问题】6.1 MQ组件重选型
ActiveMQ是一个老牌的消息队列组件 , 吞吐量方面表现不是很理想 , 适合在业务量不大的场景中使用 , 现在有非常多比较成熟及高性能高吞吐的消息队列组件可供我们选择 , 如:RabbitMQ、RocketMQ、Kafka , 后续可根据实际情况考虑替换掉ActiveMQ组件 。
 
7 总结针对消息队列的数据积压问题 , 我们主要做了三个方面的优化处理 , 取消同步锁、ActiveMQ参数优化、本地双队列优化 , 通过这三个方面的优化基本解决了队列数据积压的问题 。
文章来源:http://JAVAjgs.com/archives/5572




推荐阅读