标签:并且 rom val 关系 too imp i++ view receiver
JMS规范定义了2种消息传输模式:持久传送模式和非持久传输模式。发送者可以通过如下类似的代码进行设置
- TopicPublisher publihser = session.createPublisher(topic);
-
- publihser.setDeliveryMode(DeliveryMode.PERSISTENT);
这种方式对publisher发送的所有消息都有效,相当于是一个全局的效果。如果只是想设置某一个消息的传输模式,可以通过以下代码设置消息头的属性来实现
- TextMessage message = session.createTextMessage(text);
-
- message.setJMSDeliveryMode(DeliveryMode.PERSISTENT);
使用传输模式是一件很容易的事,直接调用API就可以了。那什么是传输模式呢?传输模式是用来控制消息属性的,DeliveryMode.PERSISTENT代表这是持久消息,DeliveryMode.NON_PERSISTENT代表是非持久消息。个人觉得传输模式和消息持久化是同一个概念,只不过是不同的叫法而已。
1.NON_PERSISTENT模式和PERSISTENT模式
对于非持久的消息,JMS provider不会将它存到文件/数据库等稳定的存储介质中。也就是说非持久消息驻留在内存中,如果jms provider宕机,那么内存中的非持久消息会丢失。A JMS provider must diliver a NON_PERSISTENT messageat-most-once。对于持久消息,消息提供者会使用存储-转发机制,先将消息存储到稳定介质中,等消息发送成功后再删除。如果jms provider挂掉了,那么这些未送达的消息不会丢失;jms provider恢复正常后,会重新读取这些消息,并传送给对应的消费者。A JMS provider must diliver a PERSISTENT messageonce-and-only-once。
2.消息是否持久和是否送达
消息的持久特性就是为了在异常发生的时候保证消息的送达。如果网络、jms provider、消息生产者、消息消费者都不会出现任何故障,那么持久消息和非持久消息就没有差别了。因为一旦消息成功传送给它的所有消费者,那么jms provider会从内存/硬盘上删除这些无用的消息。显然一切正常的情况下,使用PERSISTENT消息非常浪费,因为持久传送消息前,需要先将消息保存到硬盘;消息发送成功后,还需要将消息从硬盘上删除。但现实情况是,网络可能出现断连、provider和消费者都有可能宕机。因此对于一些非常重要,不容许任何丢失的消息,一定要采用PERSISTENT模式。
我的另一篇博客
理解JMS规范中的持久订阅和非持久订阅 介绍了持久订阅者和非持久订阅者的差别。持久订阅者和持久消息有什么区别和联系吗?持久消息发送给持久订阅者和非持久订阅有什么差别?非持久消息能够发送给持久订阅者吗?下面通过一些测试代码,来阐述持久消息和持久订阅者的关系。测试代码是基于ActiveMQ5.8.0版本。
3.1生产者发送持久消息和非持久消息,但是消息没有消费者,即这是一条无用消息
- package mq.aty.persistentmsg;
-
- import javax.jms.DeliveryMode;
- import javax.jms.Session;
- import javax.jms.TextMessage;
- import javax.jms.Topic;
- import javax.jms.TopicConnection;
- import javax.jms.TopicPublisher;
- import javax.jms.TopicSession;
-
- import mq.aty.JmsUtils;
-
- public class NoReceiverTest
- {
- private static TopicConnection connection = null;
-
- private static Topic topic = null;
-
- public static void main(String[] args) throws Exception
- {
- connection = JmsUtils.getConnection();
- topic = JmsUtils.getTopic();
-
- sentPersistent();
- sentNonPersistent();
-
- connection.close();
- }
-
- public static void sentPersistent() throws Exception
- {
- TopicSession session = connection.createTopicSession(false,
- Session.AUTO_ACKNOWLEDGE);
-
- TopicPublisher publihser = session.createPublisher(topic);
-
- publihser.setDeliveryMode(DeliveryMode.PERSISTENT);
-
- for (int i = 0; i < 3; i++)
- {
- String text = "I am persistent message.order=" + i;
-
- TextMessage message = session.createTextMessage(text);
-
- message.setJMSPriority(i);
-
- publihser.publish(message);
- }
-
- }
-
- public static void sentNonPersistent() throws Exception
- {
- TopicSession session = connection.createTopicSession(false,
- Session.AUTO_ACKNOWLEDGE);
-
- TopicPublisher publihser = session.createPublisher(topic);
-
- publihser.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
-
- for (int i = 0; i < 3; i++)
- {
- String text = "non-persistent message.id=" + i;
-
- TextMessage message = session.createTextMessage(text);
-
- publihser.publish(message);
- }
-
- }
-
- }
我使用了mysql数据库,并配置了activeMQ将消息持久化到数据库。运行上面的程序,发现mysql数据库中activemq_msgs表没有任何数据。可以证明:持久消息和非持久消息都被MQ消息服务器丢弃了。
无论是持久消息,还是非持久消息,如果消息没有对应的消费者,那么activeMQ会认为这些消息无用,直接删除。
3.2生产者发送持久消息和非持久消息,只有非持久订阅者
之前的博客已经介绍了:非持久订阅者只有在活动状态,并且和jms provider的保持连接情况下,才能收到消息。如果非持久订阅者挂掉了,那么不能再接收任何消息(无论是持久消息,还是非持久消息)。如果订阅者挂掉了,后续jms provider再收到消息,就变成了3.1的情况。也就是说:消息是否持久化,和非持久订阅者没有关系。
理解JMS规范中消息的传输模式和消息持久化
标签:并且 rom val 关系 too imp i++ view receiver
原文地址:http://www.cnblogs.com/austinspark-jessylu/p/7827638.html