• activeMQ消费消息时网络流量异常大的问题


         公司有一个应用,多个线程从activeMQ中取消息,随着业务的扩大,该机器占用的网络带宽越来越高。

    仔细分析发现,mq入队时并没有异常高的网络流量,仅仅在出队时会产生很高的网络流量。

    最终发现是spring的jmsTemplate与activemq的prefetch机制配合导致的问题。

    研究源码发现jmsTemplate实现机制是:每次调用receive()时都会创建一个新的consumer对象,用完即销毁。

    正常情况下仅仅会浪费重复创建consumer的资源代价,并不至于产生正常情况十倍百倍的网络流量。

    但是activeMQ有一个提高性能的机制prefetch,此时就会有严重的问题。

    prefetch机制:
    每次consumer连接至MQ时,MQ预先存放许多message到消费者(前提是MQ中存在大量消息),预先存放message的数量取决于prefetchSize(默认为1000)。此机制的目的很显然,是想让客户端代码用一个consumer反复进行receive操作,这样能够大量提高出队性能。

    此机制与jmsTemplate配合时就会产生严重的问题,每次jmsTemplate.receive(),都会产生1000个消息的网络流量,但是因为jmsTemplae并不会重用consumer,导致后面999个消息都被废弃。反复jmsTemplate.receive()时,表面上看不出任何问题,其实网络带宽会造成大量的浪费。


    解决方案:

    1、若坚持使用jmsTemplate,需要设置prefetch值为1,相当于禁用了activeMQ的prefetch机制,此时感觉最健壮,就算多线程,反复调用jmsTemplate.receive()也不会有任何问题。但是会有资源浪费,因为要反复创建consumer并频繁与服务器进行数据通信,但在性能要求不高的应用中也不算什么问题。

    2、不使用jmsTemplate,手工创建一个consumer,并单线程反复使用它来receive(),此时可以充分利用prefetch机制。配合多线程的方式每个线程拥有自己的一个consumer,此时能够充分发挥MQ在大吞吐量时的速度优势。

    切记避免多线程使用一个consumer造成的消息混乱。大吞吐量的应用推荐使用方案2,能够充分利用prefetch机制提高系MQ的吞吐性能。

    参考文档:

    介绍了acrivemq的prefetch机制,每次消费者读取消息时,mq会预先塞给消费者prefetchSize个消息
    而jmsTemplate取消息的实现方式为:创建consumer -> 取一个消息 -> 销毁consumer,并没有为consumer做池。
    缺省设置时, prefetchSize为1000,prefetch机制取得的后999个消息都白取了。所以必须设置prefetch值为1。
     
    activemq的spring支持,文章后半段Working with Spring's JmsTemplate 部分介绍了jmsTemplate
    jms连接池只对connection、session、producer组池,而不对consumer做池。
    因为prefetch机制的存在,如果对consumer做池,会造成池内的consumer预读取的消息很可能无法被及时处理。
  • 相关阅读:
    ts中的 接口
    微信小程序点击事件传值
    css 闪烁白点
    vue组件传值之事件总线(EventBus)
    vue 3.0优雅地使用ref获取dom元素
    JS从数组中随机取出几个数组元素的方法
    海明码
    小程序动画
    微信小程序点击图片预览
    flex 布局 子元素会撑开父元素处理
  • 原文地址:https://www.cnblogs.com/baibaluo/p/2748468.html
Copyright © 2020-2023  润新知