场景一:物联网系统经常会遇到向终端下发命令,如果命令一段时间没有应答,就需要设置成超时。
场景二:订单下单之后30分钟后,如果用户没有付钱,则系统自动取消订单。
最近的一个项目遇到了这种情况,如果运单30分钟还没有被接单,则状态自动变为已取消。实现延迟消息原理如下,借用一张图:
实现方案
-
定时任务轮询数据库,看是否有产生新任务,如果产生则消费任务
-
pcntl_alarm为进程设置一个闹钟信号
-
swoole的异步高精度定时器:swoole_time_tick(类似javascript的setInterval)和swoole_time_after(相当于javascript的setTimeout)
-
rabbitmq延迟任务
以上四种方案,如果生产环境有使用到swoole建议使用第三种方案。此篇文章重点讲述第四种方案实现

1 <?php 2 require_once __DIR__ . '/../vendor/autoload.php'; 3 use PhpAmqpLib\Connection\AMQPStreamConnection; 4 use PhpAmqpLib\Message\AMQPMessage; 5 6 7 $queue = "test_ack_queue"; 8 $exchange = "test_ack_queue"; 9 //获取连接 10 $connection = new AMQPStreamConnection('localhost', 5672, 'guest', 'guest'); 11 //从连接中创建通道 12 $channel = $connection->channel(); 13 14 $channel->exchange_declare('delay_exchange', 'direct',false,true,false); 15 $channel->exchange_declare('cache_exchange', 'direct',false,true,false); 16 17 $tale = new \PhpAmqpLib\Wire\AMQPTable(); 18 $tale->set('x-dead-letter-exchange', 'delay_exchange'); 19 $tale->set('x-dead-letter-routing-key','delay_exchange'); 20 //$tale->set('x-message-ttl',10000); 21 22 $channel->queue_declare('cache_queue',false,true,false,false,false,$tale); 23 $channel->queue_bind('cache_queue', 'cache_exchange','cache_exchange'); 24 25 $channel->queue_declare('delay_queue',false,true,false,false,false); 26 $channel->queue_bind('delay_queue', 'delay_exchange','delay_exchange'); 27 28 29 $msg = new AMQPMessage('Hello World',array( 30 'expiration' => 10000, 31 'delivery_mode' => AMQPMessage::DELIVERY_MODE_PERSISTENT 32 33 )); 34 35 $channel->basic_publish($msg,'cache_exchange','cache_exchange'); 36 echo date('Y-m-d H:i:s')." [x] Sent 'Hello World!' ".PHP_EOL; 37 38 39 40 41 //while ($wait) { 42 // $channel->wait(); 43 //} 44 45 $channel->close(); 46 $connection->close();

1 <?php 2 require_once __DIR__ . '/../vendor/autoload.php'; 3 use PhpAmqpLib\Connection\AMQPStreamConnection; 4 use PhpAmqpLib\Message\AMQPMessage; 5 6 7 //获取连接 8 $connection = new AMQPStreamConnection('localhost', 5672, 'guest', 'guest'); 9 //从连接中创建通道 10 $channel = $connection->channel(); 11 12 13 //$channel->queue_declare($queue, false, true, false, false); 14 //$channel->exchange_declare($exchange, 'topic', false, true, false); 15 //$channel->queue_bind($queue, $exchange); 16 17 18 19 $channel->exchange_declare('delay_exchange', 'direct',false,false,false); 20 $channel->queue_declare('delay_queue',false,true,false,false,false); 21 $channel->queue_bind('delay_queue', 'delay_exchange','delay_exchange'); 22 23 24 25 function process_message(AMQPMessage $message) 26 { 27 $headers = $message->get('application_headers'); 28 $nativeData = $headers->getNativeData(); 29 // var_dump($nativeData['x-delay']); 30 echo date('Y-m-d H:i:s')." [x] Received",$message->body,PHP_EOL; 31 $message->delivery_info['channel']->basic_ack($message->delivery_info['delivery_tag']); 32 33 } 34 35 36 $channel->basic_qos(null, 1, null); 37 $channel->basic_consume('delay_queue', '', false, false, false, false, 'process_message'); 38 39 function shutdown($channel, $connection) 40 { 41 $channel->close(); 42 $connection->close(); 43 } 44 register_shutdown_function('shutdown', $channel, $connection); 45 46 while (count($channel->callbacks)) { 47 $channel->wait(); 48 }
本文来自博客园,作者:孙龙-程序员,转载请注明原文链接:https://www.cnblogs.com/sunlong88/articles/10087901.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· DeepSeek在M芯片Mac上本地化部署
· 葡萄城 AI 搜索升级:DeepSeek 加持,客户体验更智能