六、RabbitMQ - PHP 操作 RabbitMQ - 死信队列的设置
hi,我是温新,一名 PHPer
版本:erlang-25.2.1、rabbitmq_server-3.11.9
系统版本:Rocky Linux 9.1
学习目标:了解死信队列
本篇文章结合官方文档编写及参考网络资料编写,虽非全部原创,但也是结合了自己的理解,若转载请附带本文 URL,编写不易,持续编写更不易,谢谢!
什么是死信队列
死信,在官网中对应的单词为“Dead Letter”。“死信”是RabbitMQ中的一种消息机制,当你在消费消息时,如果队列里的消息出现以下情况:
- 消息被拒绝,使用 channel.basicNack 或 channel.basicReject ,并且此时requeue 属性被设置为false。
- 消息在队列的存活时间超过设置的生存时间(TTL)时间。
- 消息队列的消息数量已经超过最大队列长度。
实现死信队列
如何实现死信队列?下面一起来看看。
消息被拒绝
消息被拒绝,消费者中使用 (basic.reject/basic.nack),并且 requeue = false。
# 消费者
$callback = function ($msg) {
// 拒绝接收消息
$msg->delivery_info['channel']->basic_ack($msg->delivery_info['delivery_tag']);
};
$channel->basic_qos(null, 1, null);
$channel->basic_consume($queueName,'', false,false,false,false,$callback);
消息被拒绝接收后就会进入到死信队列中。
消息过期
对于队列而言
可以使用 x-message-ttl
参数设置当前队列中所有消息的过期时间(单位毫秒)。一旦消息过期,就会从队列中删除。
// 在正常队列中设置消息过期时间
$this->channel->exchange_declare('my-logs', 'direct',false, false, false);
$args = new AMQPTable([
// 消息过期时间
'x-message-ttl' => 20000,
// 死信交换机
'x-dead-letter-exchange' => 'dead-exc',
// 死信路由键
'x-dead-letter-routing-key' => 'dead-key'
]);
$this->channel->queue_declare('user-log-1', false, true,false,false,false,$args);
$this->channel->queue_bind('user-log-1', 'my-logs', 'user');
对于单个消息
发布消息时,使用 expiration
参数设置单个消息的过期时间。要注意的是,即使消息过期,也不会马上从队列中抹去,因为每条消息是否过期是在即将投递到消费者之前判定的。
$args = new AMQPTable([
// 消息过期时间
'expiration' => 20000,
// 死信交换机
'x-dead-letter-exchange' => 'dead-exc',
// 死信路由键
'x-dead-letter-routing-key' => 'dead-key'
]);
要是两个都设置了,则以最短时间为准。
x-message-ttl 与 expiration 有什么不一样?
x-message-ttl:队列中已过期的消息在队列头部,RabbitMQ 只要定期从队头开始扫描是否有过期的消息即可。
expiration:该消息即将被消费时判断是否过期,过期则删除。
队列达到最大长度
设置队列长度限制
x-max-length
设置最大消息数;
x-max-length-bytes
设置最大长度(以字节为单位)。
如果设置了两个参数,则两者都将适用,将强制执行首先达到的限制。
$args = new AMQPTable([
// 设置最大消息数
'x-max-length' => 2,
'x-dead-letter-exchange' => 'dead-exc',
'x-dead-letter-routing-key' => 'dead-key'
]);
队列溢出行为
x-overflow
设置溢出行为,可选值为 drop-head(默认)、 reject-publish 或 reject-publish-dlx。
- drop-head:从队列前端(即队列中最旧的消息)删除或死信消息。
- reject-publish:直接丢弃最近发布的消息。假设 x-max-length = 5,发送消息 1-10,最终剩消息 1-5。
$args = new AMQPTable([
'x-max-length' => 2,
'x-overflow' => 'reject-publish',
'x-dead-letter-exchange' => 'dead-exc',
'x-dead-letter-routing-key' => 'dead-key'
]);
- reject-publish-dlx:最近发布的消息会进入死信队列。假设 x-max-length = 5,发送消息 1-10,最终消息 1-5 进入队列,消息 6-10 会进入死信队列。