Java implements the rabbitmq task model (work queues), the producer and consumer message queue can do more work

Work queues also become task queues, task models. When message processing is time-consuming, the rate of message production may be far greater than the rate of consumption. In the long run, messages will accumulate and cannot be processed in time. At this point, the work model is maliciously used to bind multiple consumers to a queue and consume messages from the queue together. Once the message in the message queue is consumed, it will disappear, so the task will not be repeated.

Insert picture description hereThrough the official documents, we can intuitively recognize this model structure. A consumer sends multiple messages to the message queue, and the corresponding multiple consumers work at the same time to consume messages.
This model is very similar to the hello word direct connection simple model we mentioned earlier, except that the consumer has changed from one to multiple to improve the efficiency of message consumption.

The creation, dependency, and tools of virtual host users and other information are omitted here.
Refer to: java implements rabbitmq simple queue model, producer consumer message queue

  1. Create
    a producer The only change from the previous producer class is to publish multiple messages at the same time so that you can observe the consumption of messages by multiple consumers.
public class Provider {
    
    
    public void send() throws IOException, TimeoutException {
    
    
        Connection connection = null;
        Channel channel = null;
        try {
    
    
            connection = ConnectionUtils.getConnection();
            // 获取连接通道
            channel = connection.createChannel();

            channel.queueDeclare("wuwl",true,false,false,null);

            for (int i = 0; i < 20; i++) {
    
    
                channel.basicPublish("","wuwl",null,("info index :" + i).getBytes());
            }

        }finally {
    
    
            if (channel !=null && channel.isOpen()) {
    
    
                channel.close();
            }
            if (connection != null && connection.isOpen()) {
    
    
                connection.close();
            }
        }
    }

    public static void main(String[] args) throws IOException, TimeoutException {
    
    
        Provider provider = new Provider();
        provider.send();
    }
}
  1. Create multiple consumers
    Consumer One:
public class Consumer01 {
    
    
    public void consume() throws IOException, TimeoutException {
    
    
        Connection connection = null;
        Channel channel = null;

        connection = ConnectionUtils.getConnection();
        // 获取连接通道
        channel = connection.createChannel();

        channel.queueDeclare("wuwl", true, false, false, null);

        channel.basicConsume("wuwl", true, new DefaultConsumer(channel) {
    
    
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
    
    
                System.out.println("消费消息:" + new String(body));
            }
        });
    }

    public static void main(String[] args) throws IOException, TimeoutException {
    
    
        Consumer01 consumer = new Consumer01();
        consumer.consume();
    }

}

Consumer 2:

public class Consumer02 {
    
    
    public void consume() throws IOException, TimeoutException {
    
    
        Connection connection = null;
        Channel channel = null;

        connection = ConnectionUtils.getConnection();
        // 获取连接通道
        channel = connection.createChannel();

        channel.queueDeclare("wuwl", true, false, false, null);

        channel.basicConsume("wuwl", true, new DefaultConsumer(channel) {
    
    
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
    
    
                System.out.println("消费消息:" + new String(body));
            }
        });
    }

    public static void main(String[] args) throws IOException, TimeoutException {
    
    
        Consumer02 consumer = new Consumer02();
        consumer.consume();
    }

}

Consumer 1 and Consumer 2 are exactly the same at this time

  1. Start consumers Start
    the two consumers before the producer and wait for the message to be sent
    Insert picture description here

  2. Start the producer
    Start the producer and send 20 messages to the message queue

  3. Analyze consumers
    Consumer one:
    Insert picture description hereConsumer two:
    Insert picture description here
    Consumer one and consumer two consume the messages in the message queue evenly. Even if the two consumers consume messages in different efficiency, they will consume evenly. Adding the consumer to the thread sleep delay, you can find that the amount of information consumed by the two consumers remains unchanged, and it is still cyclical. This is confirmed from the official documentation.
    Insert picture description here
    Therefore, work queues cannot distribute messages according to the capabilities of consumers, and can only distribute messages evenly. It will be more troublesome if messages accumulate because of a consumer's low efficiency. This is mainly determined by the message confirmation mechanism. By default, the consumer will confirm the message after receiving the message, and the message will be removed from the queue. At this time, it is unknown whether the consumer has actually completed the message. For example, if one of the consumers received 5 messages to be processed and only processed 2 of them, the server failed and the 3 lost messages could not be retrieved.

Modify the consumer message confirmation mechanism.
Consumer One:

public class Consumer01 {
    
    
    public void consume() throws IOException, TimeoutException {
    
    

        Connection connection = ConnectionUtils.getConnection();
        // 获取连接通道
        final Channel channel = connection.createChannel();
        // 每次只能消费一个消息
        channel.basicQos(1);
        channel.queueDeclare("wuwl", true, false, false, null);

        channel.basicConsume("wuwl", false, new DefaultConsumer(channel) {
    
    
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
    
    
                System.out.println("消费消息:" + new String(body));
                try {
    
    
                    Thread.sleep(10);
                } catch (InterruptedException e) {
    
    
                    e.printStackTrace();
                }
                //参数一:确认队列中的那个消息  参数二:是否开启多个消息同时确认
                channel.basicAck(envelope.getDeliveryTag(),false);
            }
        });
    }

    public static void main(String[] args) throws IOException, TimeoutException {
    
    
        Consumer01 consumer = new Consumer01();
        consumer.consume();
    }

}

Consumer 2:

public class Consumer02 {
    
    
    public void consume() throws IOException, TimeoutException {
    
    

        Connection connection = ConnectionUtils.getConnection();
        // 获取连接通道
        final Channel channel = connection.createChannel();
        // 每次只能消费一个消息
        channel.basicQos(1);
        channel.queueDeclare("wuwl", true, false, false, null);

        channel.basicConsume("wuwl", false, new DefaultConsumer(channel) {
    
    
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
    
    
                System.out.println("消费消息:" + new String(body));
                //参数一:确认队列中的那个消息  参数二:是否开启多个消息同时确认
                channel.basicAck(envelope.getDeliveryTag(),false);
            }
        });
    }

    public static void main(String[] args) throws IOException, TimeoutException {
    
    
        Consumer02 consumer = new Consumer02();
        consumer.consume();
    }}

Change 1:, channel.basicQos(1)limit the maximum number of messages sent by the queue to consumers to 1
Change 2:, change the channel.basicConsume("wuwl", false, new DefaultConsumer(channel)second parameter to false, cancel automatic message confirmation
Change 3: channel.basicAck(envelope.getDeliveryTag(),false)Manual confirmation of messages
Change 4: Thread.sleep(10)Consumers will sleep for 10 milliseconds when one consumes one, It is too long to see the effect, and it is consumed by other consumers first.
Change 5: Change the number of messages sent by the producer to 100

running result:

As soon as the consumer consumes 6 of the 100 messages, the
Insert picture description hereconsumer consumes the remaining 94.
Insert picture description here
At this time, those able to work harder are realized, and the messages in the queue will not be lost without being actually consumed, and the data is safe.

Guess you like

Origin blog.csdn.net/qq_41885819/article/details/112863109