介绍
在最开始的时候我们学习到 RabbitMQ 分发消息采用的轮询分发,但是在某种场景下这种策略并不是很好,比方说有两个消费者在处理任务,其中有个消费者 1 处理任务的速度非常快,而另外一个消费者 2 处理速度却很慢,这个时候我们还是采用轮询分发的化就会到这处理速度快的这个消费者很大一部分时间处于空闲状态,而处理慢的那个消费者一直在干活,这种分配方式在这种情况下其实就不太好,但是 RabbitMQ 并不知道这种情况它依然很公平的进行分发。
为了避免这种情况,在消费者中消费消息之前,设置参数 channel.basicQos(1);
public class Work03 {
//队列名称
public static final String TASK_QUEUE_NAME = "ACK_QUEUE";
//接受消息
public static void main(String[] args) throws IOException, TimeoutException {
Channel channel = RabbitMQUtils.getChannel();
System.out.println("C1等待接受消息处理时间较短");
DeliverCallback deliverCallback =(consumerTag,message) ->{
//沉睡1S
SleepUtils.sleep(1);
System.out.println("接受到的消息:"+new String(message.getBody(),"UTF-8"));
//手动应答
/**
* 1.消息的标记Tag
* 2.是否批量应答 false表示不批量应答信道中的消息
*/
channel.basicAck(message.getEnvelope().getDeliveryTag(),false);
};
CancelCallback cancelCallback = (consumerTag -> {
System.out.println(consumerTag + "消费者取消消费接口回调逻辑");
});
//设置不公平分发
int prefetchCount = 1;
channel.basicQos(prefetchCount);
//采用手动应答
boolean autoAck = false;
channel.basicConsume(TASK_QUEUE_NAME,autoAck,deliverCallback,cancelCallback);
}
}
开启成功,会看到如下结果:
不公平分发思想:如果一个工作队列还没有处理完或者没有应答签收一个消息,则不拒绝 RabbitMQ 分配新的消息到该工作队列。此时 RabbitMQ 会优先分配给其他已经处理完消息或者空闲的工作队列。如果所有的消费者都没有完成手上任务,队列还在不停的添加新任务,队列有可能就会遇到队列被撑满的情况,这个时候就只能添加新的 worker (工作队列)或者改变其他存储任务的策略。
#效果演示
生产者生产多个消息,两个消费者的消费时间不同,则消费消息的次数也不同