Java初识RabbitMQ一消息确认机制

Java初识RabbitMQ一消息确认机制

生产端消息确认机制

消息确认,是指生产端投递消息后,如果Broker收到消息,则会给我们生产端一个应答。生产端接收应答,用来确定这条消息是否正常发送到Broker,这种方式也是消息可靠性投递的核心保障!

消息确认机制流程图
在这里插入图片描述
如何实现消息确认机制?

我们需要实现消息确认机制,首先我们必须要开启这种机制。

        // 开启消息确认机制
        channel.confirmSelect();

confirmSelect()源码如下:

    /**
     * Enables publisher acknowledgements on this channel.
     * @see com.rabbitmq.client.AMQP.Confirm.Select
     * @throws java.io.IOException if an error is encountered
     */
    Confirm.SelectOk confirmSelect() throws IOException;

Enables publisher acknowledgements on this channel.从注释中也可以知道,通过Channel调用这个方法会开启生产端消息确认机制。

现在我们开启了生产端消息确认机制,但当Broker收到消息,给我们生产端一个应答,我们需要有处理这个应答的方法(异步回调方法处理消息发送成功或者失败,这很像博主之前用AIO模型实现的简易多人聊天室,也是异步回调),所以需要一个处理应答的回调函数,根据具体的结果对消息进行重新发送、或记录日志等后续处理,如下:

        // 添加消息确认监听(异步回调)
        channel.addConfirmListener(new ConfirmListener() {
            @Override
            public void handleAck(long deliveryTag, boolean multiple) throws IOException {
                System.out.println("------------ack---------------");
            }

            @Override
            public void handleNack(long deliveryTag, boolean multiple) throws IOException {
                System.out.println("------------no ack---------------");
            }
        });

现在我们实现了消息确认机制,生产端投递消息,Broker收到消息,给生产端一个应答,如果消息成功收到,回调函数会输出ack,否则输出no ack

生产端

我们这里使用的是默认交换机,它的路由规则可以看看下面这篇博客。
Java初识RabbitMQ一交换机(default exchange)

package com.kaven.rabbitmq.api.confirm;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.ConfirmListener;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

public class Producer {
    // 自己服务器的IP
    private static String ip = "IP";
    // RabbitMQ启动的默认端口,也是应用程序进行连接RabbitMQ的端口
    private static int port = 5672;
    // RabbitMQ有一个 "/" 的虚拟主机
    private static String virtualHost = "/";

    // default exchange
    private static String exchange = "";
    // default exchange 的路由规则: routingKey(test) 将匹配同名的 queue(test)
    private static String routingKey = "test";

    public static void main(String[] args) throws IOException, TimeoutException {
        // 1 创建ConnectionFactory
        ConnectionFactory connectionFactory = new ConnectionFactory();
        connectionFactory.setHost(ip);
        connectionFactory.setPort(port);
        connectionFactory.setVirtualHost(virtualHost);

        // 2 创建Connection
        Connection connection = connectionFactory.newConnection();

        // 3 创建Channel
        Channel channel = connection.createChannel();

        // 4 开启消息确认机制
        channel.confirmSelect();

        // 5 发送消息
        for (int i = 0; i < 10; i++) {
            String msg = "消息确认模式:RabbitMQ send confirm message "+i;
            channel.basicPublish(exchange , routingKey , null , msg.getBytes());
        }

        // 6 添加消息确认监听(异步回调)
        channel.addConfirmListener(new ConfirmListener() {
            @Override
            public void handleAck(long deliveryTag, boolean multiple) throws IOException {
                System.out.println("------------ack---------------");
            }

            @Override
            public void handleNack(long deliveryTag, boolean multiple) throws IOException {
                System.out.println("------------no ack---------------");
            }
        });
    }
}

消费端

package com.kaven.rabbitmq.api.confirm;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.QueueingConsumer;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

public class Consumer {
    // 自己服务器的IP
    private static String ip = "IP";
    // RabbitMQ启动的默认端口,也是应用程序进行连接RabbitMQ的端口
    private static int port = 5672;
    // RabbitMQ有一个 "/" 的虚拟主机
    private static String virtualHost = "/";

    // default exchange
    private static String exchange = "";
    // 队列名
    private static String queueName = "test";

    public static void main(String[] args) throws IOException, TimeoutException, InterruptedException {
        // 1 创建ConnectionFactory
        ConnectionFactory connectionFactory = new ConnectionFactory();
        connectionFactory.setHost(ip);
        connectionFactory.setPort(port);
        connectionFactory.setVirtualHost(virtualHost);

        // 2 创建Connection
        Connection connection = connectionFactory.newConnection();

        // 3 创建Channel
        Channel channel = connection.createChannel();

        // 4 创建Queue
        channel.queueDeclare(queueName , true , false , false , null);

        // 5 创建消费者
        QueueingConsumer consumer = new QueueingConsumer(channel);
        channel.basicConsume(queueName , true , consumer);

        // 6 接收消息
        while (true){
            QueueingConsumer.Delivery delivery = consumer.nextDelivery();
            String msg = new String(delivery.getBody());
            System.out.println(msg);
        }
    }
}

测试

运行生产端会发现每次运行结果都可能不一样,会有多种情况出现,因为Broker会进行优化,有时会批量一次性Confirm ,有时会分开几条Confirm。

五条。

------------ack---------------
------------ack---------------
------------ack---------------
------------ack---------------
------------ack---------------

三条。

------------ack---------------
------------ack---------------
------------ack---------------

还有其他情况就不列举了。

我们来看看RabbitMQ Management,有40条消息准备好了,因为我启动了四次生产端来进行测试。
在这里插入图片描述
现在,我们启动消费端,消费端也成功收到了这40条消息。

消息确认模式:RabbitMQ send confirm message 0
消息确认模式:RabbitMQ send confirm message 1
消息确认模式:RabbitMQ send confirm message 2
消息确认模式:RabbitMQ send confirm message 3
消息确认模式:RabbitMQ send confirm message 4
消息确认模式:RabbitMQ send confirm message 5
消息确认模式:RabbitMQ send confirm message 6
消息确认模式:RabbitMQ send confirm message 7
消息确认模式:RabbitMQ send confirm message 8
消息确认模式:RabbitMQ send confirm message 9
消息确认模式:RabbitMQ send confirm message 0
消息确认模式:RabbitMQ send confirm message 1
消息确认模式:RabbitMQ send confirm message 2
消息确认模式:RabbitMQ send confirm message 3
消息确认模式:RabbitMQ send confirm message 4
消息确认模式:RabbitMQ send confirm message 5
消息确认模式:RabbitMQ send confirm message 6
消息确认模式:RabbitMQ send confirm message 7
消息确认模式:RabbitMQ send confirm message 8
消息确认模式:RabbitMQ send confirm message 9
消息确认模式:RabbitMQ send confirm message 0
消息确认模式:RabbitMQ send confirm message 1
消息确认模式:RabbitMQ send confirm message 2
消息确认模式:RabbitMQ send confirm message 3
消息确认模式:RabbitMQ send confirm message 4
消息确认模式:RabbitMQ send confirm message 5
消息确认模式:RabbitMQ send confirm message 6
消息确认模式:RabbitMQ send confirm message 7
消息确认模式:RabbitMQ send confirm message 8
消息确认模式:RabbitMQ send confirm message 9
消息确认模式:RabbitMQ send confirm message 0
消息确认模式:RabbitMQ send confirm message 1
消息确认模式:RabbitMQ send confirm message 2
消息确认模式:RabbitMQ send confirm message 3
消息确认模式:RabbitMQ send confirm message 4
消息确认模式:RabbitMQ send confirm message 5
消息确认模式:RabbitMQ send confirm message 6
消息确认模式:RabbitMQ send confirm message 7
消息确认模式:RabbitMQ send confirm message 8
消息确认模式:RabbitMQ send confirm message 9

我们再来看看RabbitMQ Management,很显然消息已经全部被消费者接收了。

在这里插入图片描述

发布了298 篇原创文章 · 获赞 424 · 访问量 71万+

猜你喜欢

转载自blog.csdn.net/qq_37960603/article/details/104276517