码迷,mamicode.com
首页 > 其他好文 > 详细

ActiveMQ消息的事务和签收机制

时间:2020-09-24 00:03:28      阅读:36      评论:0      收藏:0      [点我收藏+]

标签:system   creates   string   意思   ups   new   catch   出错   执行   

一、消息的事务性

1、生产者  

  01、生产者不开启事务

    不开启事务的生产代码:

public class JmsQueueProducer {
    public static final String BROKER_URL = "tcp://192.168.229.129:61616";
    public static final String QUEUE_NAME = "queue01";
    public static final String TEXT_MESSAGE_NAME = "textMessage";

    public static void main(String[] args) throws JMSException {
        ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(BROKER_URL);
        Connection connection = connectionFactory.createConnection();
        connection.start();
		// 两个参数 transacted=事务,acknowledgeMode=签收模式
		// 如果生产者不开启事务,也就是transacted=false,那么第二个参数只要是符合传参的规范,就能将消息发送至MQ服务器中
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
	
        Queue queue = session.createQueue(QUEUE_NAME);
        MessageProducer producer = session.createProducer(queue);     
        producer.setDeliveryMode(DeliveryMode.PERSISTENT);
        for (int i = 1; i < 4; i++) {
            TextMessage textMessage = session.createTextMessage(TEXT_MESSAGE_NAME + i);
            producer.send(queue, textMessage);
        }
        // 释放资源
        producer.close();
        session.close();
        connection.close();
        System.out.println("生产者发送消息至MQ QUEUE......");
    }
}

  可以看出第二个参数是int类型,它的规范的值有下面这一些:

  Session.SESSION_TRANSACTED

  Session.ATUO_ACKNOWLEDGE

  Session.CLIENT_ACKNOWLEDGE

  Session.DUPS_KO_ACKNOWKEDGE

技术图片

  如果我们给acknowledge设置一个int类型的值5,看看会有什么现象

// 给第二个参数设置int类型的数字5
Session session = connection.createSession(false, 5);  

  运行程序发现报错了,报错的意思就是int类型的数字 5 不是一个有效的参数,能使用的参数下面列举出来了.

Exception in thread "main" javax.jms.JMSException: invalid acknowledgeMode: 5.
Valid values are 
Session.AUTO_ACKNOWLEDGE (1), 
Session.CLIENT_ACKNOWLEDGE (2), 
Session.DUPS_OK_ACKNOWLEDGE (3), 
ActiveMQSession.INDIVIDUAL_ACKNOWLEDGE (4)
or for transacted sessions Session.SESSION_TRANSACTED (0)
	at org.apache.activemq.ActiveMQConnection.createSession(ActiveMQConnection.java:334)
	at queue.JmsQueueProducer.main(JmsQueueProducer.java:23)

 

  02、生产者开启事务

    开启事务的生产者代码:

public class JmsQueueProducer {
    public static final String BROKER_URL = "tcp://192.168.229.129:61616";
    public static final String QUEUE_NAME = "queue01";
    public static final String TEXT_MESSAGE_NAME = "textMessage";

    public static void main(String[] args) throws JMSException {
        ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(BROKER_URL);
        Connection connection = connectionFactory.createConnection();
        connection.start();
        Session session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
        Queue queue = session.createQueue(QUEUE_NAME);
        MessageProducer producer = session.createProducer(queue);

        try {
            for (int i = 1; i < 11; i++) {
                TextMessage textMessage = session.createTextMessage(TEXT_MESSAGE_NAME + i);
                producer.send(queue, textMessage);
               if(i<=5){
                   session.commit();
               }else{
                   session.rollback();
               }
            }
            System.out.println("生产者成功发送消息至MQ QUEUE......");
        } catch (Exception e) {
            System.out.println("如果出现异常,消息回滚");
            session.rollback();
        } finally {
            // 释放资源
            producer.close();
            session.close();
            connection.close();
        }
    }
}

技术图片

  小结:

  01、生产者不开启事务的情况下,只要执行send()方法,消息就可以发送至队列,它会默认帮我们commit(),第二个参数只要是符合语法规范的有效值就可以了,理论上是任意的,但是我们比较喜欢使用ATUO_ACKNOWLEDGE

  02、生产者开启事务的情况下,执行send()方法并不会把消息发送至MQ服务器,还需要手动commit()进行提交,如果出现异常的情况下可以使用session.rollback进行回滚,由于对于生产者来说,事务的级别高于消息的应答,所以第二个参数可以忽略,一般ATUO_ACKNOWLEDGE就可以了.

  03、对于生产者来说,生产者偏向于事务,生产者发送消息到MQ队列中,不关心签收机制是什么,所以不管开启不开启事务,第二个参数一般只要给一个AUTO_ACKNOWLEDGE就可以了

 

2、消费者

  01、消费者不开启事务,自动签收的情况下,只能消费一次消息,不会重复消费消息

// 消费者不开启事务,自动应答
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);

  02、消费者开启事务、自动签收、并且手动commit(),那么消息就只能被消费一次,这样就可以保证一定的可靠性,否则消息会被重复消费

// 消费者开启事务,自动签收
Session session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
// 在session关闭之前,使用session.commit()手动提交
session.commit();

  

 

二、消息的签收机制 

  一般签收机制只对于消费者来说,对于生产者来说,它只负责发送消息,消息的签收机制对它来说没有太大意义

  1、消费者不开启事务,自动签收的情况下,消费者可以消费消息,并且只能消费一次消息,不会存在重复消费的情况

// 消费者不开启事务,自动签收
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);

  2、消费者开启事务,自动签收的情况下,必须使用commit手动提交,否则重复消费消息

// 消费者开启事务,自动签收
Session session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
// 如果没有手动提交,消费者可以重复消费消息,并且队列中的消息不会出队列
session.commit();

  3、消费者不开启事务,手动签收,必须调用acknowledge()方法来确认签收,否则会重复消费消息

// 消费者不开启事务,手动签收
Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
// 在自动签收的情况下使用message.acknowledge()方法进行签收,如果不手动调用ackonwledge()方法,那么消息会被重复消费
textMessage.acknowledge();

  4、消费者开启事务,手动签收,只调用acknowledge()方法,消息会被重复消费

// 消费者开启事务,手动签收
Session session = connection.createSession(true, Session.CLIENT_ACKNOWLEDGE);
// 如果只加上message.acknowledge()方法,消息会被重复消费
textMessage.acknowledge();

  5、消费者开启事务,手动签收,只调用commit()方法,消息不会被重复消费(事务的决定性>签收机制?)

// 消费者开启事务,手动签收
Session session = connection.createSession(true, Session.CLIENT_ACKNOWLEDGE);
// 如果只加上session.commit()方法,消息不会重复消费
session.commit();

  6、消费者开启事务,手动签收,调用commit()方法和acknowledge()方法,消息不会重复消费

// 消费者开启事务,手动签收
Session session = connection.createSession(true, Session.CLIENT_ACKNOWLEDGE);
// 加上message.acknowledge()方法
textMessage.acknowledge();
// 加上session.commit()方法
session.commit();

  

三、总结

  1、生产者

    01、对于生产者来说,它关心的仅仅只是事务,生产者只负责发送消息,消息是否签收,以及消息的签收机制对他来说没有很大意义

    02、如果生产者不开启事务,我们为了符合规范,消息签收机制那里我们给一个Session.AUTO_ACKONWLEDGE就可以了

    03、如果生产者开启事务,我们为了符合规范,消息签收机制那里我们给一个AUTO_ACKONWLEDGE,并且需要手动调用session.commit(),否则消息不会发送至MQ服务器

  2、消费者

    01、消费者一般关心的是签收方式,我们一般不开启事务,如果是自动签收,我们什么都不需要做,如果是手动签收,那么我们需要手动调用message.acknowledge()方法

    02、消费者特殊情况下如果使用事务,就需要调用session.commit()方法.

    03、特殊情况下,如果既开启了事务,又是手动签收,单单开启事务就可以避免消费重复消息

    04、为了避免出错,消费者消费消息的时候,如果开启了事务,就调用session.commit(),自动签收就是调用acknowledge(),使它们成对的出现,这样可以避免不必要的错误.

 

ActiveMQ消息的事务和签收机制

标签:system   creates   string   意思   ups   new   catch   出错   执行   

原文地址:https://www.cnblogs.com/xiaomaomao/p/13715488.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!