RabbitMQ学习七

RabbitMQ之消息确认机制(事务+Confirm)
原文的连接:https://blog.csdn.net/u013256816/article/details/55515234

RabbitMQ 为我们提供了两种方式:
生产者
1、 通过 AMQP 事务机制实现,这也是 AMQP 协议层面提供的解决方案;
2、通过将 channel 设置成 confirm 模式来实现;

以下代码是基于AMQP实现的

public class Send {

private final static String QUEUE_NAME = "QUEUE_simple";

public static void main(String[] args) throws IOException, TimeoutException {
    //链接MQ 创建channel
    Connection connection = ConnectionUtils.getConnection();
    Channel channel = connection.createChannel();

    //创建队列
    channel.queueDeclare(QUEUE_NAME, false, false, false, null);

    String message = "Hello simple";

    try {
        channel.txSelect();
        channel.basicPublish("", QUEUE_NAME, null, message.getBytes());
        int result = 1 / 0;
        channel.txCommit();
    } catch (Exception e){
        channel.txRollback();
        System.out.println("-----msg rollBack");
    }finally {
        System.out.println("---------send msg over:" + message);
    }
    channel.close();
    connection.close();
}
}

在这里插入图片描述
AMQP的实现主要是在生产者一方去做事物的管理,消费者的代码还是一尘不变

public class Consumer {
    private static final String QUEUE_NAME = "QUEUE_simple";

    public static void main(String[] args) throws Exception {
        Connection connection = ConnectionUtils.getConnection();
        Channel channel = connection.createChannel();
        channel.queueDeclare(QUEUE_NAME, false, false, false, null);
        DefaultConsumer consumer = new DefaultConsumer(channel) {
            //获取到达的消息
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope,
                                       AMQP.BasicProperties properties, byte[] body) throws IOException {
                String message = new String(body, "UTF-8");
                System.out.println(" [x] Received '" + message + "'");
            }
        };
        //监听队列
        channel.basicConsume(QUEUE_NAME, true, consumer);
    }
}
+

下面代码是基于confirm模式实现的

public class SendConfirm {

    private final static String QUEUE_NAME = "QUEUE_simple_confirm";

    public static void main(String[] args) throws IOException, TimeoutException, InterruptedException {
        //链接MQ 创建channel
        Connection connection = ConnectionUtils.getConnection();
        Channel channel = connection.createChannel();

        //创建队列
        channel.queueDeclare(QUEUE_NAME, false, false, false, null);

        //生产者通过调用channel的confirmSelect方法将channel设置为confirm模式
        channel.confirmSelect();

        String message = "Hello simple";

        channel.basicPublish("", QUEUE_NAME, null, message.getBytes());

        if(!channel.waitForConfirms()){
            System.out.println("send message failed.");
        }else{
            System.out.println(" send messgae ok ...");
        }
        channel.close();
        connection.close();
    }
}

在这里插入图片描述
这是异步的confirm方式在这里插入图片描述

public class SendAync {
    private static final String QUEUE_NAME = "QUEUE_simple_confirm_aync";
    public static void main(String[] args) throws IOException, TimeoutException {
        /* 获取一个连接 */
        Connection connection = ConnectionUtils.getConnection();
        /* 从连接中创建通道 */
        Channel channel = connection.createChannel();
        channel.queueDeclare(QUEUE_NAME, false, false, false, null);
        //生产者通过调用channel的confirmSelect方法将channel设置为confirm模式
        channel.confirmSelect();
        final SortedSet<Long> confirmSet = Collections.synchronizedSortedSet(new
                TreeSet<Long>());
        channel.addConfirmListener(new ConfirmListener() {
        //每回调一次handleAck方法,unconfirm集合删掉相应的一条(multiple=false)或多条(multiple=true)记录。
            @Override
            public void handleAck(long deliveryTag, boolean multiple) throws
                    IOException {
                if (multiple) {
                    System.out.println("--multiple--");
                    confirmSet.headSet(deliveryTag + 1).clear();//用一个SortedSet, 返回此有序集合中小于end的所有元素。
                } else {
                    System.out.println("--multiple false--");
                    confirmSet.remove(deliveryTag);
                }
            }
            @Override
            public void handleNack(long deliveryTag, boolean multiple) throws
                    IOException {
                System.out.println("Nack, SeqNo: " + deliveryTag + ", multiple:" + multiple);
                if (multiple) {
                    confirmSet.headSet(deliveryTag + 1).clear();
                } else {
                    confirmSet.remove(deliveryTag);
                }
            }
        });
        String msg = "Hello QUEUE !";
        while (true) {
            long nextSeqNo = channel.getNextPublishSeqNo();
            channel.basicPublish("", QUEUE_NAME, null, msg.getBytes());
            confirmSet.add(nextSeqNo);
        }
    }
}

这是批量的confirm模式,其实和第一种confirm模式不同的就是发消息的时候是通过循环去发送的来达到批量的目的
在这里插入图片描述
消费者的代码还是和之前一样,这里不是关注点

public class Consumer {
//    private static final String QUEUE_NAME = "QUEUE_simple";
    private static final String QUEUE_NAME = "QUEUE_simple_confirm_aync";

    public static void main(String[] args) throws Exception {
        Connection connection = ConnectionUtils.getConnection();
        Channel channel = connection.createChannel();
        channel.queueDeclare(QUEUE_NAME, false, false, false, null);
        DefaultConsumer consumer = new DefaultConsumer(channel) {
            //获取到达的消息
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope,
                                       AMQP.BasicProperties properties, byte[] body) throws IOException {
                String message = new String(body, "UTF-8");
                System.out.println(" [x] Received '" + message + "'");
            }
        };
        //监听队列
        channel.basicConsume(QUEUE_NAME, true, consumer);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值