JMS如何保证消息的可靠性?

JMS如何保证消息的可靠性?

JMS是通过持久化(Persistent)、事务(Transaction)、 签收来(acknowledge)保证的

image.png

1、持久化

首先消息的持久化是在消息的生产者中设置的,由消息的生产者告诉消息中间件是否进行消息的持久化,如果生产者端没有设置,默认是持久化的
通过session创建出来的生产者生产的Queue消息为持久性

  • 持久化:当服务器宕机,消息依然存在;当服务器再次重启,消息能够被消费者继续消费。
  • 非持久化:当服务器宕机,消息不会被保留。

设置通过session创建出来的生产者生产的Queue消息为持久性
messageProducer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);//非持久化 messageProducer.setDeliveryMode(DeliveryMode.PERSISTENT);//持久化

生产者代码实现:

public class JmsProducer {

   public static final String ACTIVEMQ_URL="tcp://192.168.137.199:61616";
   public static final String QUEUE_ANME="queue01";

   public static void main(String[] args) throws JMSException {
       //1.创建连接工厂
       ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory("admin","admin",ACTIVEMQ_URL);
       //2.通过连接工厂,获得连接connection并启动访问
       Connection connection = activeMQConnectionFactory.createConnection();
       connection.start();
       //3.创建会话session
       // 两个参数:事务/签收
       Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
       //4.创建目的地(队列或主题topic)
//        Destination destination = session.createQueue(QUEUE_ANME);
       Queue queue = session.createQueue(QUEUE_ANME);
       //5.创建消息的生产者
       MessageProducer messageProducer = session.createProducer(queue);
//        messageProducer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);//非持久化
//        messageProducer.setDeliveryMode(DeliveryMode.PERSISTENT);//持久化
       //6 通过使用messageProducer生产3条消息发送到MQ的队列里面
       for (int i = 1; i <=3; i++) {
           //7创建消息
//            TextMessage textMessage = session.createTextMessage("msg--" + i);
           TextMessage textMessage = session.createTextMessage("textMessage msg--" + i);
           //8.通过messageProducer发送给mq
           messageProducer.send(textMessage);
       }
       //9.关闭资源
       messageProducer.close();
       session.close();
       connection.close();
       System.out.println("MQ消息发布成功");

   }
}

消费者代码实现:

public class JmsConsumer {
    public static final String ACTIVEMQ_URL="tcp://192.168.137.199:61616";
    public static final String QUEUE_ANME="queue01";

    public static void main(String[] args) throws JMSException, IOException {
        System.out.println("*****我是2号消费者");

        //1.创建连接工厂
        ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory("admin","admin",ACTIVEMQ_URL);
        //2.通过连接工厂,获得连接connection并启动访问
        Connection connection = activeMQConnectionFactory.createConnection();
        connection.start();
        //3.创建会话session
        // 两个参数:事务/签收
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        //4.创建目的地(队列或主题topic)
//        Destination destination = session.createQueue(QUEUE_ANME);
        Queue queue = session.createQueue(QUEUE_ANME);
        //5.创建消费者
        MessageConsumer messageConsumer = session.createConsumer(queue);

        while (true){
            TextMessage message = (TextMessage) messageConsumer.receive(20000L);
            if(null != message){
                System.out.println("TX消费者接收到消息:"+message.getText());
//                message.acknowledge();
            }else {
                break;
            }
        }

//        System.in.read();//保证控制台不关闭
        messageConsumer.close();
  //      session.commit();
        session.close();
        connection.close();

    }
}

持久化消息是队列的默认传递模式,此模式保证这些消息只被传送一次和成功使用一次。对于这些消息,可靠性是优先考虑的因素。

可靠性的另一个重要方面是确保持久性消息传送至目标后,消息服务在向消费者传送它们之前不会丢失这些消息。

2、事务

消息生产者偏重于事务,开启事务后生产者生产的消息,只有在session执行commit后才会被提交到服务器,不然此次提交记录无效。事务开启的意义在于,如果对于多条必须同批次传输的消息,可以使用事务,如果一条传输失败,可以将事务回滚,再次传输,保证数据的完整性。

如果开启事务,事务优先级>签收;

  • 在事务性会话中,当一个事务被成功提交则消息被自动签收。
  • 如果事务回滚,则消息会被再次传送
  • 对于消费者而言,如果开启事务,createSession设置为 ture,消费消息需要commit,否则会出现多次消费的情况
//这边的第一个参数true表示事务开启
Session session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
//事务如果是true:  需要commit
session.commit();

3、签收

消费者偏重于签收
签收主要针对于消费者,而且一般在非事务的情况下生效,因为开启事务后,签收与否取决于事务的提交或回滚,与签收设置的方式无关。

签收方式有4种,但平时常用的有两种:

  1. 自动签收
Session.AUTO_ACKNOWLEDGE;//自动签收
  1. 手动签收
Session.CLIENT_ACKNOWLEDGE; //手动签收
message.acknowledge();  // 手动签收需要ack
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容