一、前言
之前我们演示了,如何通过rabbitmq实现消息队列的,而且是一个生产者对应一个消费者,那我现在想一个生产者对应多个消费者,又会有什么样的情况发生呢?
二、消息分发轮询
2.1、分发轮询实验
前提条件:1个生产者 ----> 多个消费者,且no_ack=True #no_ack--->no acknowledgement--->不确定
①初始化状态:3个消费者都在等待生产者发消息
②生产者发第1条消息:只有第1个消费者受到消息,第2个和第3个消费者没有收到消息
③生产者发第2条消息:只有第2个消费者受到消息,第1个和第3个没有收到的消息
④生产者发第3条消息:只有第3个收到消息,第1个和第2个没有收到消息。
总结:一个生产者对应多个消费者是采用轮询机制,公平的依次发给每一个消费者,每个消费者消费1个。
三、消息分发过程中突然中断
现在说,我这个消费者受到这个消息之后,就立刻打印了,假如说这个消费者收到这个消息之后,需要处理这个消息花费30s时间,在处理这个30s的过程中,消费者断电了,也就是down及了,那这个任务只处理了一半,还没有处理完毕。
遇到这种情况该如何解决呐?
这种情况就需要去怎么样定义的你的业务逻辑了。如果你认为这个任务必须要处理完,那就是应该这个消费者把这个任务处理完了,给生产者发一个确认。也就是说代表我处理完了。处理完了之后,生产者会把这个消息从这个消息队列中删除,就代表着这个任务确实处理完了,所以生产者一定等消费者把这个任务处理完了之后,告诉生产者,说处理完了,生产者才会把这个消息从队列中删除。
回到刚才那个问题,如果没有处理完,处理了一半,down机了,它就没有办法告诉生产者,所以在这个时候生产者应该如何解决呐?
生产者说,只要你没有给我回复确认,就代表消息没有处理完,也不用设置超时时间,你只要没有确认,就代表消息没有处理完。也就是callback函数处理完了,就代表消息处理完了,callback没有处理完,就是消息没有处理完。
3.1、no_ack参数
说明:no_ack 意思是 no acknowlargement 不确定的意思,如果这个no_ack=True 表示你服务器不care也不关心这个消息是否处理完了,但是如果你关系的话,我们就不加。一般情况下,我们是不加的,rabbitmq 默认就是说消息处理完了,自动确认。
就是说只要客户端没有给它确认,RabbitMQ就不会把这个消息删掉,生产者那一端没有删除。
3.2、处理过程中down机的效果图
①初始化状态:3个消费者都在等生产者发消息
②生产者发消息:第1个消费者受到消息,第2个和第3个没有收到消息。
③第1个消费者down机:第1个消费者down机,则消息则发送到第2个消费者那边去了。
④第2个消费者down机:第2个消费者down机,则消息则发送到第3个消费者那边去了。
总结:只要把这个no_ack=True注释掉,就能保证消息被完整的处理。它存在RabbitMQ的sever的那个队列里面。
3.3、逻辑图
四、总结
- 一个生产者对应多个消费者,生产者发送多次消息,是采用轮询的机制,公平的分给每一个消费者。
- 消费者代码中no_ack=True,一般情况下是不加的,保证了连接断开,消息就会转给下一个消费者。
- RabbitMQ判断如果socket断了,就知道连接断了,消息就会转给下一个消费者。
- 消费者的启动顺序,代表着是第几个消费者。