zoukankan      html  css  js  c++  java
  • activeMQ消费消息时网络流量异常大的问题

    http://www.cnblogs.com/baibaluo/archive/2012/12/24/2748468.html#2590289

    公司有一个应用,多个线程从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预读取的消息很可能无法被及时处理。
  • 相关阅读:
    Android存储数据方式(转)
    Android实现双进程守护 (转)
    Android DOM、SAX、Pull解析XML(转)
    TCP/IP和Socket的关系(转)
    Socket通信原理和实践
    [转]Android中Intent传递对象的两种方法(Serializable,Parcelable)
    内存堆和栈的区别
    hdu 1754 线段树
    hdu 1166 线段树
    zoj 3686 线段树
  • 原文地址:https://www.cnblogs.com/sunxucool/p/3240924.html
Copyright © 2011-2022 走看看