RabbitMQ官網(wǎng)教程翻譯(PHP版本)_5

本文所有內(nèi)容均個人從RabbitMQ官網(wǎng)教程中翻譯,若圖片文字的引用有任何侵權(quán)的地方,聯(lián)系我,我會立馬刪除。

This article was translated from RabbitMQ Official Tutorials by myself,and if this article and the images in this article have any infringement,please contact to me, and i will delete them.

話題

(使用php-amqplib
在上一個教程我們升級了我們的日志系統(tǒng)。與僅僅能夠進行虛擬廣播的fanout類型交換機不同,我們使用了一個direct類型交換機,并獲得了可以選擇性地接收日志的能力。

盡管使用direct交換機提升我們的系統(tǒng),但它仍然是由限制的——它不能夠在多個標(biāo)準(zhǔn)下進行路由。

在我們的日志系統(tǒng)中,我們可能希望不僅僅是根據(jù)日志等級來訂閱日志,也可以根據(jù)發(fā)送日志的源。你可能已經(jīng)從可以同時根據(jù)日志的嚴(yán)重性(info/warn/crit....)與設(shè)施(auth/cron/kern...)來路由日志的Unixsyslog工具知道這一概念。

這會帶給我們非常多的靈活性——我們可能打算僅僅監(jiān)聽來自cron的嚴(yán)重錯誤日志而又監(jiān)聽來自kern的所有日志。

為了在我們的日志系統(tǒng)實現(xiàn)這一公功能,我們需要學(xué)習(xí)一個更加復(fù)雜的topic交換機

Topic交換機

消息發(fā)送到一個topic交換機不能隨意設(shè)置routing_key——它必須是一系列以點分隔的詞。這些詞可以是隨意的,但它們通常指定了消息的一些特性。有一些有效的路由鍵(routing key)的例子:'stock.usd.nyse'nyse.vmwquick.orange.rabbit。他們可以由很多你喜歡的路由鍵組成,最多不能超過255個字節(jié)(bytes)

綁定鍵(binding key)也必須是同樣的格式。topic交換機的邏輯與direct交換機是相似的——一條攜帶特定路由鍵(routing key)發(fā)送的消息將會被分發(fā)到所有以與之匹配的綁定鍵(binding key)綁定的Queue(隊列)。然而,關(guān)于綁定鍵,有兩個需要特別注意的情況:

  1. *(星號)可以代替(任意)一個詞。
  2. (井號)可以代替零個或者更多的詞

這是一個最簡單的解釋例子:


topic exhange model

在這一個例子中,我們準(zhǔn)備發(fā)送一些描述動物的消息。這些消息被發(fā)送時將會帶有由三個單詞組成(兩個點)的路由鍵(routing key)。路由鍵(routing key)的第一個詞將會描述速度,第二個描述顏色,第三個描述物種:'<speed>.<colour>.<species>'

我們創(chuàng)建了三個綁定:Q1隊列以'*.orange.*路由鍵綁定,Q2'*.*.rabbitlazy.#(兩個路由鍵)綁定。

這些綁定可以概括為:
Q1對所有orange(橙色)的動物感興趣。
Q2想監(jiān)聽rabbit(兔子)的所有消息與lazy(慢吞吞的)動物的所有消息。

一條路由鍵(routing key)被設(shè)置為'quick.orange.rabbit的消息將會被交付到這兩個隊列。路由鍵為'lazy.orange.elephant'的消息也會被交付到這兩個隊列。而另一種路由鍵為'quick.orange.fox'的消息只會去到第一個(Q1)隊列,以及'lazy.brown.fox'只會發(fā)送到第二個(Q2)隊列。路由鍵為lazy.pink.rabbit的消息只會被發(fā)送到第二個(Q2)隊列一次,盡管它符合兩個綁定。'quick.brown.fox'不匹配任何一個綁定,所以它會被丟棄。

如果我們打破我們的規(guī)定,發(fā)送了一條只帶有一個詞或者帶有四個詞的路由鍵的消息,例如'orange'或者'quick.orange.male.rabbit',會發(fā)生什么呢?這些消息將不會匹配到任何綁定上并且將會被丟失。

在另一方面,盡管'lazy.orange.male.rabbit'擁有四個詞,它將會匹配最后一個綁定lazy.#,并將會發(fā)送到第二個隊列。


話題交換機(Topic Exchange)

話題交換機是十分強大的,同時它能表現(xiàn)得想其他的交換機一樣。
當(dāng)一個Queue(隊列)"#"(井號)綁定鍵(binding key)綁定——它將會忽視路由鍵(routing key)去接收所有消息就像是一個fanout類型的交換機一樣。

當(dāng)特殊字符"*"(星號)"#"(井號)沒有被用在綁定(鍵)上,這時候topic交換機由表現(xiàn)得像direct交換機一樣。


把他們一起運行

我們準(zhǔn)備在我們的日志系統(tǒng)中使用一個topic交換機。我們將從一個工作假設(shè)開始,即日志的路由鍵將有兩個單詞:"<facility>.<severity>"

代碼與上一個教程的十分相似,

emit_log_topic.php的代碼如下:

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

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

// 聲明一個topic交換機
$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);

// 攜帶路由鍵發(fā)送到topic_logs交換機
$channel->basic_publish($msg, 'topic_logs', $routing_key);

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

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

receive_logs_topic.php的代碼如下:

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

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

// 聲明topic交換機
$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();
?>

如果想接收所有日志:

php receive_logs_topic.php "#"

接收"kern"設(shè)備的所有日志:

php receive_logs_topice.php "kern.*"

或者你只想監(jiān)聽"critical"的日志:

php receive_logs_topic.php "*.critical"

你可以創(chuàng)建多個綁定:

php receive_logs_topic.php "kern.*" "*.critical"

以及,發(fā)送一個帶有"kern.critical"路由鍵的日志請輸入:

php emit_log_topic.php "kern.critical" "A critical kernel error"

用這些程序愉快地玩耍吧。要主意的是,這些代碼是沒有對路由或綁定鍵做任何的假設(shè),你可能希望使用兩個兩個以上的路由鍵參數(shù)。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容