RabbitMQ(二)——工作队列
(原创内容,转载请注明来源,谢谢)
一、概述
工作队列模式(work queue),是有多个消费者的情况下,可以共同消费队列内的内容,加快消息处理速度。这是RabbitMQ的基本工作模式。
二、使用方式
和上一篇中的生产和消费消息的方式一样,就是需要多在cli进程中打开一个消费者的php文件。即需要打开3个php,一个是生产者的php文件,两个消费者的php文件(或多个php文件)。
三、工作机制
3.1 轮询(Round-robin dispatching)
当开启多个生产者的时候,消费者产生消息并发送到队列的情况下,队列会将消息均衡的分发给同时打开的多个消费者。即采用轮询的方式,假设有两个消费者c1和c2,第一次有消息给c1,第二次有消息给c2,第三个再给c1,以此类推。
3.2 回馈机制(Message acknowledgment)
为了保证消息的可靠性,RabbitMQ允许用户采用消费者的ack机制,即只有消费者回馈给队列ack后,队列才会将消息从队列中剔除。这样,可以确保队列中的每个消息都是确认被消费者处理完毕的。
开启的方式,只要将方法basic_consume第四个参数设置成false,就表示开启ack机制。
开启ack,就必须要记得在消费者的代码总,加入回馈的代码,否则,消息会被队列认为没有消费,不断的堵在队列中,导致队列堵塞。
要查看队列中还没确认的内容,可以采用RabbitMQ的管理工具——rabbitmqctl。
sudo rabbitmqctl list_queues namemessages_ready messages_unacknowledged
3.3 消息持久化(Message durability)
RabbitMQ具有完善的持久化机制,能够确保消息的安全性。可以在代码中开启持久化。消息持久化需要在队列和消息分别开启持久化。
1)队列持久化:
queue_declare的第三个参数设置为true。
2)消息持久化:
$msg = new AMQPMessage($data,
array('delivery_mode' =>AMQPMessage::DELIVERY_MODE_PERSISTENT)
);
这样可以确保消息可以保存在本地磁盘,因此即使rabbitmq的服务器宕机的时候,也可以保证消息的安全性。
当然,这也也存在一定的风险,因为操作系统自身的机制,开启持久化的时候,操作系统为了保证运作速度,消息会保存在操作系统层面的缓存,并且定时将消息存入硬盘。因此,还没存入磁盘的这一小段间隔(30秒左右),如果服务器宕机,有可能消息丢失。但是这个可能性很低,因此安全性已经很高。
3.4 公平分发(Fair dispatch)与预取机制(prefetch)
消息的轮询机制,每次有消息,队列则直接按照排好的顺序将消息传给对应的队列,有可能出现一部分队列上一条消息还没处理完,就出现了下一条的消息,而另外一部分队列则空闲的情况。
因此,RabbitMQ允许用户开启公平分发机制,让每个消费者只能接收一个消息,如果还没给队列回复ack,则消息来的时候,即使顺序轮到队列,也不会分发给它,而是分发给它下一个空队列。
开启方式很简单,在消费者的channel,在消费消息之前(使用basic_consume方法),给channel加一个qos机制:
$channel->basic_qos(null, 1, null);
第二个参数就是要求消费者每次只能处理几个消息。
这样也存在一个隐患,即如果所有的消费者都还没ack,而生产者又不断的往队列发数据,则队列有可能会塞满。这个处理方案只有增加消费者,或者从代码、逻辑层面控制消息的产生速度。
——written by linhxx 2017.08.19