RabbitMQ 工作模型

工作模型

第一种直连的模型,如果消息过多会让队列阻塞。当消息处理比较耗时间的时候,可能生产消息的速度会远远大于消息的消费速度,长此以往消息会堵塞。因此rabbitmq提供了工作模型,让多个消费之绑定一个队列,共同消费队列中的消息。

P消息提供者,C1消息消费者1 C2消息消费者2

Provider程序

package com.baizhi.workqueue;

import com.baizhi.Utils.rabbitmqUtils;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;

import java.io.IOException;

public class Provider {
    public static void main(String[] args) {
        Connection connection= rabbitmqUtils.getConnection();
        try {
            Channel channel=connection.createChannel();
            channel.queueDeclare("work",true,false,false,null);
            for(int i=0;i<10;i++){
                channel.basicPublish("","work",null,("HelloWork"+i).getBytes());

            }
            rabbitmqUtils.closeChannlAndConnection(channel,connection);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

Customer1

package com.baizhi.workqueue;

import com.baizhi.Utils.rabbitmqUtils;
import com.rabbitmq.client.*;

import java.io.IOException;

public class Customer {
    public static void main(String[] args) {
        Connection connection= rabbitmqUtils.getConnection();
        try {
            Channel channel=connection.createChannel();
            channel.queueDeclare("work",true,false,false,null);
            channel.basicConsume("work",true,new DefaultConsumer(channel){
                @Override
                public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                    System.out.println("消费者1--->"+new String(body));
                }
            });
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

消费者2

package com.baizhi.workqueue;

import com.baizhi.Utils.rabbitmqUtils;
import com.rabbitmq.client.*;

import java.io.IOException;

public class Customer1 {
    public static void main(String[] args) {
        Connection connection= rabbitmqUtils.getConnection();
        try {
            Channel channel=connection.createChannel();
            channel.queueDeclare("work",true,false,false,null);
            channel.basicConsume("work",true,new DefaultConsumer(channel){
                @Override
                public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                    System.out.println("消费者2--->"+new String(body));
                }
            });
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

执行结果如下

在不做任何设置情况下,消费者1,2 平均消费消息

官方文档的说明

平均消费消息,这也就是负载均衡

但是,这带来一个问题,如果消费者1消费消息慢,消费者2 消费快,此时两者仍然平均消费消息,就不合理。

rabbitmq消息确认机制

当消息发送到消息队列中时,消费队列将消息平均分配给两个消费者。第二个参数是autoAck,当其为true时,消费者自动向rabbitmq确认消息消费。它不管消息是否被消费完,都会向队列自动确认,队列自动删除消息。如果在实际应用中,队列向消费者发送五个消息,但是消费者消费了三个消息之后自己待机了,两个消息丢失。这时候队列却认为已经成功发送五个消息,并且删除这五个消息。

channel.basicConsume("work",true,new DefaultConsumer(channel){
             

我们需要将未发送的消息发送给其他消息消费者。

能者多劳机制的实现

首先关闭自动确认机制,其次消息通道中只能容纳一个消息,这样就不会造成消息的丢失。开启手动确认机制,消息发过来之后自动确认是否接收到消息,如果接收到,队列再次发送消息。

首先设置通道只有一个消息

channel.basicQos(1);//每次通道只有一个消息

关闭自动确认
 

channel.basicConsume("work",false,new DefaultConsumer(channel){
           

消费完消息后开启手动确认

//手动确认机制,参数一手动确认消息标志,参数二是不是每次确认多个消息,如果是false那么每次只确认一个消息
                    channel.basicAck(envelope.getDeliveryTag(),false);

执行效果如下

猜你喜欢

转载自blog.csdn.net/weixin_41066584/article/details/109094972