您的位置:

RabbitMQ Exclusive详解

一、Exclusive概述

Exclusive queue(独有队列)是一个仅有一个连接(connection)的消费者能访问的队列。当connection关闭时, RabbitMQ会删除这个队列。换句话说,这种队列适用于只要有一个连接消费就可以的场景,而不适合多个连接消费的场景。

连接指的是在客户端与RabbitMQ服务器之间建立的通信连接,可以看作是一个TCP连接。当从服务器退出的时候,客户端与服务器的连接关闭,包括所有它们创建的队列和交换器都会被删除。

在某些特殊情况下,如果连接关闭,但是你不想要队列被自动删除,可以使用autodelete参数。这个参数默认为true,表示只要与这个queue连接的channel(通道)关闭,那么这个queue就会自动删除。但是,当autodelete=false的时候,只有当所有相关的channel都关闭的时候这个queue才会自动删除。

二、Exclusive使用步骤

1.创建一个独有的非持久化的Queue

try {
    //创建连接,这里RabbitMQ服务器地址为localhost,端口号为5672,你需要使用你自己的主机名和端口号
    ConnectionFactory factory = new ConnectionFactory();
    factory.setHost("localhost");
    factory.setPort(5672);
    Connection connection = factory.newConnection();
    //创建通道
    Channel channel = connection.createChannel();
    //声明队列(Queue)
    String queueName = "myQueue";
    boolean durable = false;
    boolean exclusive = true;
    boolean autoDelete = false;
    channel.queueDeclare(queueName, durable, exclusive, autoDelete, null);
} catch (IOException | TimeoutException e) {
    e.printStackTrace();
}

2.发送消息到队列中

try {
    //创建连接,这里RabbitMQ服务器地址为localhost,端口号为5672,你需要使用你自己的主机名和端口号
    ConnectionFactory factory = new ConnectionFactory();
    factory.setHost("localhost");
    factory.setPort(5672);
    Connection connection = factory.newConnection();
    //创建通道
    Channel channel = connection.createChannel();
    //声明队列(Queue)
    String queueName = "myQueue";
    boolean durable = false;
    boolean exclusive = true;
    boolean autoDelete = false;
    channel.queueDeclare(queueName, durable, exclusive, autoDelete, null);
    //发送消息
    String message = "Hello RabbitMQ";
    channel.basicPublish("", queueName, null, message.getBytes());
} catch (IOException | TimeoutException e) {
    e.printStackTrace();
}

3.消费队列中的消息

try {
    //创建连接,这里RabbitMQ服务器地址为localhost,端口号为5672,你需要使用你自己的主机名和端口号
    ConnectionFactory factory = new ConnectionFactory();
    factory.setHost("localhost");
    factory.setPort(5672);
    Connection connection = factory.newConnection();
    //创建通道
    Channel channel = connection.createChannel();
    //声明队列(Queue)
    String queueName = "myQueue";
    boolean durable = false;
    boolean exclusive = true;
    boolean autoDelete = false;
    channel.queueDeclare(queueName, durable, exclusive, autoDelete, null);
    //创建消费者
    Consumer 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("接收到的消息:" + message);
        }
    };
    channel.basicConsume(queueName, true, consumer);
} catch (IOException | TimeoutException e) {
    e.printStackTrace();
}

三、Exclusive相关问题解答

1.何时使用独有队列?

我们通常在以下情况下使用独占队列:

(1)在使用多个channel去处理消息的时候,独占队列可以确保消息只会被其中一个channel消费。这一点在当我们需要处理优先级时尤其重要。

(2)在我们需要确保这个队列在只要还有消费者在处理消息时不会被自动删除时。

2.如果想要多个不同的连接去处理同一个队列,怎么办?

独占队列的使用适用于只有一个连接消费的场景。如果要多个不同的连接去处理同一个队列,那么我们不能使用独占队列。需要使用非独占队列,并且需要确保消息的时序。

3.队列和连接的生命周期是如何管理的?

队列和连接是由RabbitMQ服务器管理的。每个连接如果没有活动时间的限制,都会持续存在服务器上。当连接关闭的时候,服务器会自动关闭相关的队列和Exchange。