ActiveMQ 之消息可靠性保证

一、创建生产者代码

public class QueueProducer {

    private static final String ACTIVEMQ_URL = "tcp://localhost:61616";
    private static String queneName = "myQueue1";

    public static void main(String[] args) throws JMSException {


        //创建连接工厂
        ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(ACTIVEMQ_URL);
        //创建连接
        Connection connection = connectionFactory.createConnection();
        //打开连接
        connection.start();
        //创建会话
       Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        //创建队列
        Queue queue = session.createQueue(queneName);
        //创建生产者
        MessageProducer producer = session.createProducer(queue);
        for(int i = 0 ; i < 3 ; i++){
            //创建文本消息
            TextMessage textMessage = session.createTextMessage("第" + i + "个文本消息");
            //发送消息
            producer.send(textMessage);
            System.out.println("生产者生产消息:"+textMessage.getText());
        }
        //关闭连接
        producer.close();
        session.close();
        connection.close();
        System.out.println("生产消息完成");
    }
}

二、创建消费者代码

public class QueueConsumer {

    private static final String ACTIVEMQ_URL = "tcp://localhost:61616";
    private static String queneName = "myQueue1";

    public static void main(String[] args) throws JMSException, IOException {
        //创建连接工厂
        ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(ACTIVEMQ_URL);
        //创建连接
        Connection connection = connectionFactory.createConnection();
        //开启连接
        connection.start();
        //创建会话 第一个参数为是否开启事务,第二个参数是消息签收方式为自动签收
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        //创建队列
        Queue queue = session.createQueue(queneName);
        //创建消费者
        MessageConsumer consumer = session.createConsumer(queue);
        //接收消息
        consumer.setMessageListener(new MessageListener() {
            @Override
            public void onMessage(Message message) {
                if(message instanceof TextMessage){
                    TextMessage textMessage = (TextMessage) message;
                    try {
                        System.out.println("消费者消费消息:"+textMessage.getText());
                    } catch (JMSException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        System.in.read();
        consumer.close();
        session.close();
        connection.close();
        System.out.println("消费消息完成");
    }
}

三、ActiveMQ消息可靠性

如何保证消息可靠性?可从消息生产者、消费者、以及消息中间件三方面来分析

1、从消息生产者来说

生产者将数据发送到 MQ 的时候,可能数据就在半路给搞丢了,因为网络问题啥的,都有可能。此时可以选择用MQ 提供的事务功能,就是生产者发送数据之前开启 MQ 事务然后发送消息,如果消息没有成功被MQ 接收到,那么生产者会收到异常报错,此时就可以回滚事务,然后重试发送消息;如果收到了消息,那么可以提交事务

上述代码中connection.createSession()方法的第一个参数,即设置是否开启事务,默认是不开启事务,如果设置为true,需要进行commit,消息才会被发送到队列中去,即设置session.commit()

try{
    session.commit();
}catch{
    session.rollback();
}finally{
    session.close();
}

2、从消息消费者来说

刚消费到,还没处理,结果进程挂了,MQ 认为你都消费了,这数据就丢了。这个时候得用MQ 提供的 ack 机制,简单来说,就是你必须关闭MQ 的自动 ack,然后每次你自己代码里确保处理完的时候,再在程序里 ack

connection.createSession()方法的第二个参数,即设置签收方式,Session.AUTO_ACKNOWLEDGE 为自动签收,Session.CLIENT_ACKNOWLEDGE 为手动签收。设置手动签收的时候,需要调用textMessage.acknowledge()方法来表示接收消息成功

3、从消息中间件MQ本身来说

就是 MQ 自己弄丢了数据,这个你必须开启MQ 的持久化,就是消息写入之后会持久化到磁盘,哪怕是 MQ 自己挂了,恢复之后会自动读取之前存储的数据,一般数据不会丢。除非极其罕见的是,MQ 还没持久化,自己就挂了,可能导致少量数据丢失,但是这个概率较小

(1)、设置消息持久化:
messageProducer.setDeliveryMode(DeliveryMode.PERSISTENT)

(2)、设置消息非持久化:
messageProducer.setDeliveryMode(DeliveryMode.NON_PERSISTENT)

(3)、队列的默认传送方式是持久化的,此模式保证这些消息只被传送一次和成功使用一次

(4)、持久化的主题(Subscriber):

一定要先运行一次消费者,类似于像MQ注册,表明我订阅了这个主题。
然后再运行生产者生产消息,此时,无论消费者是否在线,都会接收到,不在线的话,下次连接的时候,会将没收到的消息接收过来

4、事务和签收的关系
在事务性会话中,当一个事务被成功提交则消息被自动签收。
如果事务回滚,则消息会被再次传送。

非事务性会话中,消息何时被确认取决于创建会话时的应答模式(acknowledgementmode)

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值