實現原理:給佇列的訊息設定過期時間(TTL),訊息到期後就會投遞到一個死信佇列,我們就可以在這裡處理延遲的任務。
一、介紹
1. 死信佇列
當訊息在一個佇列中變成死信之後,它會被重新投遞到設定的Exchange中,這個Exchange就是DLX,透過routing_key的繫結投遞到對應的佇列,這個佇列就是死信佇列。
2. 死信訊息
- 訊息被拒絕(basic.reject / basic.nack),並且requeue = false。
- 訊息TTL過期。TTL:Time To Live的簡稱,即過期時間。
- 佇列達到最大長度。
3. 過期訊息
- 透過佇列進行設定,設定後該佇列所有的訊息都存在相同的過期時間。
- 透過對訊息本身設定,佇列中的每條訊息的過期時間都可以不一樣。如果要用來實現延遲佇列不建議使用這種方式,因為佇列只會判斷第一個訊息是否過期,過期則把訊息投遞到死信佇列。如果第一個訊息過期時間為30s,二個訊息的過期時間為10s,那麼佇列等30s後把第一訊息投遞到死信佇列,然後繼續判斷下一個訊息,但是這樣子第二個訊息的延遲時間就變成30s了。
二、原理圖
三、上程式碼
composer require php-amqplib/php-amqplib
把程式碼貼到根目錄的public.php檔案執行<?php use PhpAmqpLib\Message\AMQPMessage; require_once __DIR__ . '/vendor/autoload.php'; //配置資訊 $conn_args = array( 'host' => '47.107.237.18', 'port' => '5672', 'login' => 'guest', 'password' => 'guest', 'vhost' => '/' ); $ttl = 10;//過期時間 $exchange = 'exchange';//正常交換機 $delayExchange = 'delayed_' . $exchange;//死信交換機 $type = 'topic'; $msg = 'hello world'; $route = 'delay'; $deadQueue = 'dead_queue';//死信佇列 $delayQueue = 'delayed_queue_' . $exchange . '_' . $ttl;//延遲佇列 $delayRoutingKey = $route . '_' . $ttl; $conn = new \PhpAmqpLib\Connection\AMQPStreamConnection( $conn_args['host'], $conn_args['port'], $conn_args['login'], $conn_args['password'], $conn_args['vhost'] ); //建立連線和channel $channel = $conn->channel(); //定義延遲交換器 $channel->exchange_declare($delayExchange, 'topic', false, true, false); //定義延遲佇列, $channel->queue_declare( $delayQueue, false, true, false, false, false, new \PhpAmqpLib\Wire\AMQPTable( array( "x-dead-letter-exchange" => $delayExchange,/*佇列資訊超時後投遞到這個交換機*/ "x-dead-letter-routing-key" => $route,/*routingKey*/ "x-message-ttl" => $ttl * 1000,/*超時時間*/ ) ) ); /*定義死信佇列,延遲佇列超時的訊息就會投遞到這裡處理*/ $channel->queue_declare( $deadQueue, false, true, false, false ); /*繫結死信佇列到延遲交換機*/ $channel->queue_bind($deadQueue, $delayExchange, $route); //繫結延遲佇列到交換器上 $channel->queue_bind($delayQueue, $delayExchange, $delayRoutingKey); //生產者傳送訊息 $msg = new AMQPMessage($msg); $channel->basic_publish($msg, $delayExchange, $delayRoutingKey); $channel->close();
謝謝觀看,日常記錄!
streetlamp 敬上!
本作品採用《CC 協議》,轉載必須註明作者和本文連結