php实现rabbitmq延迟队列

本文介绍了如何在RabbitMQ中安装并启用延迟消息交换机插件,以及通过PHP使用`php-amqplib`库进行消息发布和消费。首先从官方地址下载并安装插件,然后配置交换机参数,接着创建并发送带有延迟时间的消息到队列,最后展示如何接收并处理这些延迟消息。示例代码详细展示了整个过程。

1.安装插件
地址:https://www.rabbitmq.com/community-plugins.html
在这里插入图片描述
2.将其放到rabbitmq的插件目录plug

mv /www/wwwroot/rabbitmq_delayed_message_exchange-3.8.0.ez /usr/local/rabbitmq/plugins/

3.开启插件

[root@dcdfa0e9eb71 sbin]# ./rabbitmq-plugins enable rabbitmq_delayed_message_exchange
Enabling plugins on node rabbit@dcdfa0e9eb71:
rabbitmq_delayed_message_exchange
The following plugins have been configured:
  rabbitmq_delayed_message_exchange
  rabbitmq_management
  rabbitmq_management_agent
  rabbitmq_web_dispatch
Applying plugin configuration to rabbit@dcdfa0e9eb71...
The following plugins have been enabled:
  rabbitmq_delayed_message_exchange

started 1 plugins

查看插件安装列表

在这里插入图片描述
在ui界面查看

在这里插入图片描述

  • 管理控制台声明 x-delayed-message 交换机
    在开始代码之前先打开 RabbitMQ 的管理 UI 界面,声明一个 x-delayed-message 类型的交换机,否则你会遇到下面的错误:
  • 交换机名和代码的交换机名称要一样
atal error:  Uncaught exception 'PhpAmqpLib\Exception\AMQPProtocolChannelException' with message 'PRECONDITION_FAILED - Invalid argument, 'x-delayed-type' must be an existing exchange type' in /www/wwwroot/default/example/delay-mq/vendor/php-amqplib/php-amqplib/PhpAmqpLib/Channel/AMQPChannel.php:216

详情可见 Github Issues rabbitmq-delayed-message-exchange/issues/19,正确操作如下图所示

在这里插入图片描述

2.代码
安装扩展包

composer require php-amqplib/php-amqplib:2.12.3

publish.php

<?php
require_once __DIR__.'/vendor/autoload.php';
use PhpAmqpLib\Connection\AMQPStreamConnection;
use PhpAmqpLib\Message\AMQPMessage;
use PhpAmqpLib\Wire\AMQPTable;



$exchange = "delayed-order";//交换机名称
$queue = "delayQueue"; //队列名
$routing_key = 'dead-x-key'; //交换机路由key
$ttl = 20000; //单位豪秒

//1.建立连接
$connection = new AMQPStreamConnection('127.0.0.1','5672','zk','123456','/');
//2.创建信道
$channel = $connection->channel();
//2.声明交换机
$args = array('x-delayed-type' => 'direct');
$channel->exchange_declare($exchange,"x-delayed-message",false, true, false,false,$args);
//3.声明创建队列
$channel->queue_declare($queue, false, true, false, false,false);
//4.绑定交换机和队列
$channel->queue_bind($queue,$exchange,$routing_key);
//5.创建消息内容
$data = ['orderId'=>rand(10001,99999)];
$options = array(
    'delivery_mode' => AMQPMessage::DELIVERY_MODE_PERSISTENT,   //消息持久化
    'application_headers' => new AMQPTable(['x-delay' => $ttl])
);
$msg = new AMQPMessage(json_encode($data),$options);
//发送消息
$channel->basic_publish($msg,$exchange,$routing_key);
$channel->close();
$connection->close();
var_dump("发送成功",$data);


consume.php

<?php
require_once __DIR__.'/vendor/autoload.php';
use PhpAmqpLib\Connection\AMQPStreamConnection;
use PhpAmqpLib\Message\AMQPMessage;
use PhpAmqpLib\Wire\AMQPTable;

$exchange = "delayed-order";//交换机名称
$queue = "delayQueue"; //队列名
$routing_key = 'dead-x-key'; //交换机路由key
$ttl = 20000; //单位豪秒


//1.建立连接
$connection = new AMQPStreamConnection('127.0.0.1','5672','zk','123456','/');
//2.创建信道
$channel = $connection->channel();
//2.声明交换机
$channel->exchange_declare($exchange,"x-delayed-message",false, true, false);
//3.绑定交换机和队列
$channel->queue_bind($queue,$exchange,$routing_key);

//4.消费队列中的数据
$callback = function ($msg){
    $data = json_decode($msg->body,true);
    var_dump($msg->body);
    $id = $data['orderId'];
    //todo 做一些数据库或者业务逻辑的处理
//    sleep(3);
    echo "\n已完成".$id."的处理\n";
    $msg->ack();
};

//公平调度,新的消息将发送到一个处于空闲的消费者。
$channel->basic_qos(null, 1, null);

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

//没有消息时候等待
while(count($channel->callbacks)){
    $channel->wait();
}


//关闭信道
$channel->close();
//关闭连接
$connection->close();

结果:等待20s后进入队列
在这里插入图片描述

### 取消或解决RabbitMQ中的延迟队列问题 在处理RabbitMQ中的延迟队列问题时,可以采取几种方法来取消或解决问题。具体取决于所遇到的具体情况。 #### 方法一:移除未完成的任务 如果存在不需要再执行的延迟任务,可以通过`zremrangebyscore`命令从Redis的{queue}:delayed集合中删除特定分数范围内的成员[^2]。这适用于当不再希望某些任务被执行的情况: ```bash ZREMRANGEBYSCORE {queue}:delayed -inf <current_timestamp> ``` 此命令会清除所有早于当前时间戳的任务,从而有效地取消这些任务。 #### 方法二:调整插件配置 对于由`rabbitmq_delayed_message_exchange`插件引起的延迟队列行为,可考虑重新评估该插件设置是否合理。若要禁用延迟功能,则需卸载对应的插件并重启服务[^3]: ```bash rabbitmq-plugins disable rabbitmq_delayed_message_exchange systemctl restart rabbitmq-server ``` 不过需要注意的是,这样做会影响整个系统的消息调度机制,因此建议仅在必要时采用这种方式。 #### 方法三:优化消费者逻辑 有时延迟现象可能是由于消费者的处理能力不足造成的。此时应该审查消费端代码,确保其能够高效地处理接收到的消息。例如,在Laravel框架内实现的任务分发器中,应当确认每个job类都实现了合理的排队策略[^1]: ```php public function handle() { // 处理业务逻辑... } ``` 通过提高单个worker实例的工作效率或者增加并发worker的数量都可以缓解因消费速度跟不上生产速率而导致的消息堆积问题。 #### 方法四:监控与诊断工具 利用像Logstash这样的日志收集平台可以帮助追踪来自不同源头的日志记录,包括但不限于RabbitMQ本身产生的警告信息。借助此类工具能更快定位潜在性能瓶颈所在之处,并据此作出相应调整[^5]。 ### 结论 针对不同的应用场景可以选择合适的方式来应对RabbitMQ里的延迟队列挑战。无论是直接清理过期条目还是改进整体架构设计都是可行的选择方案之一。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值