Rabbitmq - 死信队列、延迟队列

死信队列

简介

死信(Deal Letter)是rabbitmq中的一种消息机制,当出现以下情况:

  • 消息被拒绝
  • 消息在队列的存活时间超过设置的TTL时间(延迟队列)
  • 消息队列的消息数量已经超过最大队列长度

那么该消息将成为"死信"。

"死信"消息将会被Rabbitmq进行特殊处理,如果配置了死信队列信息,那么该消息将会被丢进死信队列中,如果没有配置,那么该消息将会被丢弃。

RabbitMq中有一种交换器叫DLX,全称为Dead-Letter-Exchange,可以称为死信交换器。当消息在一个队列中变成死信之后,它会被重新发送到另外一个交换器中,这个交换器就是DLX,绑定在DLX上的队列称为死信队列。

延迟队列(延时队列)

简介

延迟队列(delay queue)就是用来存放需要在指定时间内被处理的元素的队列

应用场景

例子:

  • 订单在十分钟之内未支付则自动取消
  • 账单在一周内未支付,则自动结算
  • 用户注册成功后,如果三天内没有登陆则进行短信提醒
  • 用户发起退款,如果三天内没有得到处理则通知相关运营人员

生产者

<?php
require_once __DIR__ . '/vendor/autoload.php';

use PhpAmqpLib\Connection\AMQPStreamConnection;
use PhpAmqpLib\Message\AMQPMessage;
use PhpAmqpLib\Wire\AMQPTable;

$v_host = 'test';
$exc_name = 'delay_exc'; //交换器名
$routing_key = 'delay_routicg_key';
$queue_name = 'delay_queue';
$dead_queue_name = 'dead_queue';
$dead_exc_name = 'dead-exc';
$dead_routing_key = 'dead_key';
$ttl = 20000;//必须为整数型,不可加引号 毫秒单位
//地址 端口 用户名 密码 vhost
$connection = new AMQPStreamConnection('localhost', 5672, 'rabbitmq', 'rabbitmq', $v_host);

//新建通道
$channel = $connection->channel();

//声明交换器 参数:交换器名、模式、不存在则自动创建、持久化、不自动消亡
$channel->exchange_declare($exc_name, 'direct', false, true, false);
//设置消息过期时间、设置死信交换器名、死信路由键
$args = new AMQPTable(['x-message-ttl' => $ttl, 'x-dead-letter-exchange' => $dead_exc_name, 'x-dead-letter-routing-key' => $dead_routing_key]);
//声明队列
$channel->queue_declare($queue_name, false, true, false, false, false, $args);
//队列绑定交换器
$channel->queue_bind($queue_name, $exc_name, $routing_key);

//声明死信交换器
$channel->exchange_declare($dead_exc_name, 'direct', false, false, false);
//声明死信队列
$channel->queue_declare($dead_queue_name, false, true, false, false);
//死信队列绑定死信交换器
$channel->queue_bind($dead_queue_name, $dead_exc_name, $dead_routing_key);

//消息 参数:消息 、持久化
$data = 'this is dead message';
$msg = new AMQPMessage($data, [
    'delivery_mode' => AMQPMessage::DELIVERY_MODE_PERSISTENT
]);
//将消息推送到交换器里
$channel->basic_publish($msg, $exc_name, $routing_key);

//关闭通道
$channel->close();
$connection->close();

消费者

<?php
require_once __DIR__ . '/vendor/autoload.php';

use PhpAmqpLib\Connection\AMQPStreamConnection;
use PhpAmqpLib\Message\AMQPMessage;

$v_host = 'test';
$dead_queue_name = 'dead_queue';
$dead_exc_name = 'dead-exc';
$dead_routing_key = 'dead_key';
//地址 端口 用户名 密码 vhost
$connection = new AMQPStreamConnection('localhost', 5672, 'rabbitmq', 'rabbitmq', $v_host);

//新建通道
$channel = $connection->channel();
//声明交换器 参数:交换器名、模式、不存在则自动创建、持久化、不自动消亡
$channel->exchange_declare($dead_exc_name, 'direct', false, true, false);
// $channel->queue_declare($dead_queue_name, false, false, true, false);

$channel->queue_bind($dead_queue_name, $dead_exc_name, $dead_routing_key);

$callback = function ($msg) {
    var_dump('received :' . $msg->body);
    $msg->ack();
};
//一次只消费一条消息,未确认消费前不可消费其他消息
$channel->basic_qos(null, 1, null);

$channel->basic_consume($dead_queue_name, '', false, false, false, false, $callback);

while ($channel->is_open()) {
    $channel->wait();
}
//关闭通道
$channel->close();

posted @ 2022-08-28 21:51  Myifb  阅读(169)  评论(0)    收藏  举报