目录
★ 工作队列介绍
工作队列: 就是让多个消费者竞争消费同一个消息队列的消息,相当于多个消费者共享消息队列。
▲ RabbitMQ可以让多个消费者竞争消费同一个消息队列
▲ 消息队列默认会将消息"均分"给每个消费者,但这样做往往并不合适:
因为有的消费者需要更多时间处理一条消息,有的消费者只要更少时间即可处理一条消息,
如果让它们"均分"这些消息,就会造成资源浪费。
▲ 比较理想的做法是"能者多劳",让队列将消息多分给需要更少时间的消费者(快),
将消息少分给需要更多时间的消费者(慢)。
▲ 调用Channel的basicQos(int prefetchCount)方法可控制消费者在同一时间点最多能得到的消息数量
------此时应该采用手动确认。
这个就是上一篇写的采用自动确认策略 :
注意: channel.basicConsume 的第二个参数 autoAck:true,就是表示自动确认消息已经被消费完成了。就是当消费者接收到消息之后,就立马返回一个已经确认消费的消息回去给消息队列。
这样容易出现问题,就是消费者这边因为一收到消息就会自动确认消息被消费了并返回已经消费消息的结果回去给消息队列,但是可能消费者其实还没有把消息消费掉,而消息队列那边又以为消费者已经把消息消费了,所以就继续发消息给那个消费者。
而消费者一收到消息又自动确认消费并返回,就会导致这个消息队列的消息越来越多,然后消费者消费不完。
代码演示
在上一篇的代码基础上修改
200、使用默认 Exchange 实现 P2P 消息 之 消息生产者(发送消息) 和 消息消费者(消费消息)
思路:
1、创建一个消息生产者和两个消息消费者。
2、生产者发送20条消息
3、消费者01 和 消费者 02 都用 channel.basicQos(3); 设置同一时间点只能获取3条消息来处理,只有这3条消息处理完才能再次获取3条消息
4、每个消费者都在消息处理完之后添加 channel.basicAck() 这个方法来手动确认消息成功消费并返回确认成功消费的消息给消息队列。
5、消费者01 每次消费完后,先睡眠个1秒,再手动确认消息已经消费,消费者02不需要,当消息消费完成后就马上手动确认。用于看两个消费者的消费情况
代码如图:
生产者 Producer
生产者代码不变,只是设置发送20条消息
消费者01 Consumer01
经过测试:同一时间点每次只能消费3条消息,只有这3条消息消费完成,并手动确认消费完成后,才能再获取3条消息进行消费。如果把手动确认消费的代码注释掉,那么这个消费者只能消费到3条消息。最后面有演示:
消费者02 Consumer02
多个了睡眠1秒再手动确认消息
测试
生产者发送20条消息,消费者01 和 消费者02 每次获取3条消息,消息消费并手动确认后才能再获取3条消息进行消费。
然后消费者02 因为每次消费完都睡眠一秒,而消费者01没有。
这个睡眠 用来演示消费者01的消息处理速度比消费者02 快的情况。
所以那个消费者消费的快,哪个消费者处理的消息就越多
这个就是工作队列:
工作队列 就是让多个消费者竞争消费同一个消息队列的消息,相当于多个消费者共享消息队列。
注意点1:
如图:这个 multiple 参数,设置为false,表示 不对之前未确认的的消息进行批量确认。
可以经过测试,无论改成true还是false,只要消息队列里面有已消费未确认的消息,再次启动这个消费者,它还是会对之前已消费未确认的消息进行批量确认。
测试流程:
1、首先,关闭消费者,然后生产者发送20条消息。
现在就是消息队列有20条消息未被消费
2、这时候把确认消费的代码注释掉,然后如图,成功消费3条消息,但是未确认,还有17条消息待消费。
3、重新启动消费者01,这个时候正确应该是消费剩下的17条消息,但是那3条消费未确认的消息应该还在。
但是结果却如图:
重启消费者01,把自动确认的代码放开,multiple 为 false,但是最终还是把所有消息消费了,包括3条已消费未确认的消息。
所以感觉这个 multiple 为 false 没起作用。
注意点2:
注释掉手动确认代码的演示: 经过测试:同一时间点每次只能消费3条消息,只有这3条消息消费完成,并手动确认消费完成后,才能再获取3条消息进行消费 。如果把手动确认消费的代码注释掉,那么这个消费者只能消费到3条消息