[rabbitMQ]八、rabbitMQ隊列之主題模式(topic)

基於多個標準執行路由操作:在我們的日誌系統中,我們不只希望訂閱基於嚴重程度的日誌,同時還希望訂閱基於發送來源的日誌。

主題交換機

發送到主題交換機(topic exchange)的消息不可以攜帶隨意什麼樣子的路由鍵(routing_key),它的路由鍵必須是一個由.分隔開的詞語列表。這些單詞隨便是什麼都可以,但是最好是跟攜帶它們的消息有關係的詞彙。以下是幾個推薦的例子:“stock.usd.nyse”, “nyse.vmw”, “quick.orange.rabbit”。詞語的個數可以隨意,但是不要超過255字節。
綁定鍵也必須擁有同樣的格式。主題交換機背後的邏輯跟直連交換機很相似 —— 一個攜帶着特定路由鍵的消息會被主題交換機投遞給綁定鍵與之想匹配的隊列。但是它的綁定鍵和路由鍵有兩個特殊應用方式:

1)* (星號) 用來表示一個單詞.

2)#(井號) 用來表示任意數量(零個或多個)單詞。

生產者:

<?php

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

$connection = new AMQPStreamConnection('localhost', 5672, 'guest', '123456');
$channel = $connection->channel();

$channel->exchange_declare('topic_logs', 'topic', false, false, false);

$routing_key = isset($argv[1]) && !empty($argv[1]) ? $argv[1] : 'anonymous.info';
$data = implode(' ', array_slice($argv, 2));
if(empty($data)) $data = "Hello World!";

$msg = new AMQPMessage($data);

$channel->basic_publish($msg, 'topic_logs', $routing_key);

echo " [x] Sent ",$routing_key,':',$data," \n";

$channel->close();
$connection->close();

?>

消費者:

<?php

require_once __DIR__ . '/vendor/autoload.php';
use PhpAmqpLib\Connection\AMQPStreamConnection;

$connection = new AMQPStreamConnection('localhost', 5672, 'guest', '123456');
$channel = $connection->channel();

$channel->exchange_declare('topic_logs', 'topic', false, false, false);

list($queue_name, ,) = $channel->queue_declare("", false, false, true, false);

$binding_keys = array_slice($argv, 1);
if( empty($binding_keys )) {
    file_put_contents('php://stderr', "Usage: $argv[0] [binding_key]\n");
    exit(1);
}

foreach($binding_keys as $binding_key) {
    $channel->queue_bind($queue_name, 'topic_logs', $binding_key);
}

echo ' [*] Waiting for logs. To exit press CTRL+C', "\n";

$callback = function($msg){
    echo ' [x] ',$msg->delivery_info['routing_key'], ':', $msg->body, "\n";
};

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

while(count($channel->callbacks)) {
    $channel->wait();
}

$channel->close();
$connection->close();

測試:(C表示消費者程序,P表示生產者程序)
1) C: 接收所有錯誤日誌:

php receive_log_topic.php "#"

2) C: 接收來自”kern“設備的日誌:

php receive_log_topic.php "*.critical"

3) C: 接收嚴重程度爲critical的錯誤日誌:

php receive_log_topic.php "*.critical"

4) C: 接收嚴重程度爲critical,並且設備來源是kern的錯誤日誌:

php receive_log_topic.php "kern.*" "*.critical"

5)P: 發送路由鍵爲 “kern.critical” 的日誌

php emit_log_topic.php "kern.critical" "A critical kernel error"
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章