4.ActiveMQ消息发送策略【同步发送 && 异步发送】

在ActiveMQ中,消息分为持久化消息非持久化消息。消息的持久化特性,通过producer.setDelivery()方法来设置。

MessageProducer producer = session.createProducer(destination);
//DeliveryMode.NON_PERSISTENT--持久化
//DeliveryMode.NON_PERSISTENT--非持久化
producer.setDeliveryMode(DeliveryMode.PERSISTENT);

消息的发送,分为同步发送(sync)异步发送(async)。接下来我们来详细讲解ActiveMQ消息的发送策略。

1.同步发送 VS 异步发送

       消息的同步和异步发送,是ActiveMQ的两个特性。这两个特性主要是在消息发送端---至--->Broker之间的一个概念。ActiveMQ支持同步、异步两种模式,来讲消息发送至Broker上。

       同步同步发送过程中,发送者发送一条消息会阻塞,直到Broker反馈给一个确认消息,表示消息已经被Broker处理。这个机制提供了消息的安全性保障,但是由于是阻塞的操作,【会影响到消息从生产者发送到Broker上的性能

       异步:异步发送的过程中,发送者不需要等待Broker提供反馈,所以性能相对较高。但是可能会出现消息丢失的情况。所以使用异步发送的前提,是在允许出现数据丢失的情况下使用

       策略选择:异步发送或者同步发送,在不同的情况下有不同的策略。那就是持久化策略非持久化策略。在默认情况下,【非持久化消息是异步发送的非持久化消息 && 非事务模式下是同步发送的】,但是在开启事务的情况下,消息都是异步发送的。因为异步发送的效率会比同步发送性能更快,所以【在发送持久化消息的时候,尽量去开启事务会话

      如何设置同步/异步发送:除了持久化消息和非持久化消息的同步和异步特性外,我们还可以通过以下三种方式来设置异步发送:

//1.直接在brokerUrl中设置
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://192.168.204.201:61616?jms.useAsyncSend=true");
//2.直接在connectionFactory中设置属性
((ActiveMQConnectionFactory)connectionFactory).setUseAsyncSend(true);
//3.直接在当前connection设置属性
((ActiveMQConnection)connection).setUseAsyncSend(true);

2.ActiveMQ消息发送流程图

4.ActiveMQ消息发送策略【同步发送 && 异步发送】_第1张图片

流程解析

   1. producer.send( )方法,默认是异步发送,在发送过程中,会判断producerWindow是否有空间;

   2. 如果说没有空间,则它会处于阻塞(Blocking)状态;

   3. 如果空间被释放,当消息被Broker端确认后,producerWindow窗口会递减,此时,在Broker端会发送一个onProducerACK消息,producerWindow会递减消费后的消息的大小;

  4. 此时Blocking状态,又会恢复为一个可运行状态;

  5. 如果producerWindow存在空间大小的话,会再次判断是不是异步发送。其实在步骤1中就已经有一个判断了。默认是异步发送的,只有异步发送,才会存在producerWindow这个概念;

  6. 如果是异步发送,会增加producerWindow的空间大小;

  7. 再会通过传输层,去发送消息至Broker上.至此,异步发送结束;

  8. 同步发送的情况下,会经过传输层,此时会处于阻塞(Blocking)状态;

  9. 消息最终,还是会发送至Broker,最后Broker再返回相关数据。

3.ProducerWindowSize概念解读

       ProducerWindowSize概念,是producer允许积压的消息的大小,仅针对异步情况下有效。通过producerWindowSize能够控制待确认的消息的大小。
       异步发送情况下,producer每发送一个消息,都会统计一下发送的字节数,当字节数达到ProducerWindowSize值时,需要等待broker的确认,确认当前剩余的空间是否做够接收新消息(大小),然后才能继续发送。

  如何设置消息发送窗口(ProducerWindowSize)的大小?

       1.通过jms.producerWindowSize=xxx来设置

         在brokerUrl中设置:"tcp://192.168.204.201:61616?jms.producerWindowSize=xxx",这种设置将会对所有的producer生效。

       2.也可以destinationUri中通过producer.windowSize=xxx设置

         在destinationUri中设置:session.setQueue("myQueue?producer.windowSize=xxx"),这种设置只对使用此Destionation实例的producer生效,这这个设置将会覆盖brokerUrl中设置的producerWindowSize值。注意:此值越大,意味着消耗的内存也会越大。

4.ActiveMQ消息发送源码分析

   如需了解源码,请点击:ActiveMQ消息发送【源码分析】

END

你可能感兴趣的:(ActiveMQ,ActiveMQ消息发送策略)