spring+activemq(4)-异步消息限流

一、序言

       有时候我们追求最快的方式发送消息,我们就采用的异步方式,并且不持久化。但是这样带来的问题有这样几个:

       1.如果消费者的消费能力低于生产者,那么消息就会积压在broker, 从而导致broker 可能挂掉。

       

       2.我们知道存放内存的模式,只要出现宕机或者其他问题,容易丢消息,因此得看情况而定

          对于问题1,activemq 采用了限流 内存溢出提醒的方式进行处理,下面是一些实例过程。

          官方介绍可以参考:http://activemq.apache.org/producer-flow-control.html

 

二、操作过程:

       1.我用的activemq.5.11 版本,下载下来打开conf/activemq.xml默认配置改为异步persistent=false

       

 <broker xmlns="http://activemq.apache.org/schema/core" persistent="false"  brokerName="localhost" dataDirectory="${activemq.data}">

       同时开启限流模式,未了测试方便,我们限流5M

 

      

<policyEntry queue=">" producerFlowControl="true" memoryLimit="5mb" />
# 经过测试 producerFlowControl 是默认开启的

    这里有原文信息:

 

    

Note that, since the introduction of the new file cursor in ActiveMQ 5.x, non-persisted messages are shunted into the temporary file store to reduce the amount of memory used for non-persistent messaging. As a result, you may find that a queue's memoryLimit is never reached, as the cursor doesn't use very much memory. 
英文不好,大概意思是:
activemq 5.0 以后引入了new file cursor ,非持久化消息会分流到temporary file 存储,用来减少实际内存使用。结果你会发现queue 的内存限制,无法超标,cursor 不会消耗很多内存。
这里有个疑问,反正temporary file 我是没看到- -,不知道为什么
注意:这里是每个queue 限制5M,不是总的

   

 

    2.测试方式:

       打开borker,然后发送10W消息到queue,你可以看到到了一定条数,producer 就不动了,这时候你再打开customer ,才会正常消费。   

 

     3.当内存达到limit 限制的时候,我们可能需要做其他处理,方便我们得知,比如:让生产者异常

     

<systemUsage>
 <systemUsage sendFailIfNoSpace="true">
   <memoryUsage>
     <memoryUsage limit="20 mb"/>
   </memoryUsage>
 </systemUsage>
</systemUsage>

    然后生产者,或者说客户端就可以捕获:javax.jms.ResourceAllocationException

 

 当然这个会直接抛出异常,后面了个属性,表示5秒后才抛出这个异常。

  

 <systemUsage sendFailIfNoSpaceAfterTimeout="5000">

 

 

    我们捕获异常之后就可以持续发送消息之后,就可以做其他处理了,broker 也不会爆掉了。

 

    3.Disabling Flow Control 不控制流量的做法

       其实这是为了使用整个服务器的配置资源,也就是说上面是单个控制,这里是整体控制

       

# 默认的系统配置,分别代表
#memoryUsage 内存
#storeUsage 持久化
#tempUsage 临时数据
#当整体数据 操作下面的时候,才爆异常,就不用单个控制了
# 比如用异步 非持久化 测试,Memory percent used 到100 就不动了
# 这部分的使用可以参考:
# http://akuntamukkala.blogspot.com/2014/01/understanding-memory-usage-in-activemq.html

<systemUsage>
  <systemUsage>
    <memoryUsage>
      <memoryUsage limit="64 mb" />
    </memoryUsage>
    <storeUsage>
      <storeUsage limit="100 gb" />
    </storeUsage>
    <tempUsage>
      <tempUsage limit="10 gb" />
    </tempUsage>
  </systemUsage>
</systemUsage>

 

 

三、基础伪代码

     

    @Autowired
    private Destination destination;
    @Autowired
    JmsTemplate jmsTemplate;

    @Test
    public void Sender(){
        for(int i=0;i<50000;i++){
            sendMsg(i);
        }
    }
    // 消息发送
    private void sendMsg(int i){
        try {
            jmsTemplate.convertAndSend(destination,""+i);
        }catch (Exception e){
            sendMsg(i);
        }
    }

   

   

<bean id = "jmsTemplate" class = "org.springframework.jms.core.JmsTemplate">
        <!-- 链接工长 -->
        <property name="connectionFactory" ref="cachingConnectionFactory"/>
        <!-- 1:非持久化,2:持久化 -->
        <property name="deliveryMode" value="1" />
        <!-- 消息转换器 -->
        <property name="messageConverter" ref="msgConvert"/>
    </bean>
<!-- 队列的目的地描述 -->
    <bean id="queueDestination" class="org.apache.activemq.command.ActiveMQQueue">
        <!-- 通过 构造 设定 队列的名字 -->
        <constructor-arg index="0" value="orderQueue"/>
    </bean>

 

四、测试步骤:

       1.开启broker,开启限流5M

       2.发送queue 10W消息,如果没配置异常,则会一直阻塞,配置了则会抛异常

       3.阻塞之后开启消费者,消息能正常收到。

 

小结:

     1.这里将官网的东西拿来做了个简单的说明和解释,如果需要这里的详细实习,得去看ActiveMQMessageProducer 类

    2.我这里用的spring +mq 的形式,如果用原生的东西,有朋友没测试成功,测试的时候尽量剔除其他东西,比如事务之类的。。

    3.有朋友问自己发送了1W消息,为什么控制台只有几千条,因为你发送1W消息其实达到limit 限制之后,后面的消息没有进入quque,因此你在控制台看到的消息是没有那么多的,假设是8K条,而且你的1W消息 只是根据发送点打印的,没进入queue.那么那些消息去哪儿了呢?源码还没具体分析,但是肯定是在内存中,没进入队列。

      这种场景我们很好思考:我限制房间只有100个人,但是来的人很快,一次来10-20个,那么满了的时候就会剩下一些在门口进不去,而客户端觉得我已经发送了120个人过去了。。。,实际我房间只有100个,实际多的20个还在客户端的发送队列里面,如果这时候客户端挂了,那么消费者只能收到100个~。~

       4.这种场景是允许的,如果保证消息不丢失,那么就要持久化的,一般高效的东西都会容忍这类事件的。

       5.有错误的请指点,不胜感谢~。~

 

 

 

 

你可能感兴趣的:(activemq,memoryLimit,activmq 限流)