RabbitMQ 入門 - Hello World

學冰發表於2018-03-26

基於 官方文件 翻譯

介紹

RabbitMQ 是一個訊息代理:它接受和轉發訊息。 你可以把它想象成一個郵局:當你把你想要釋出的郵件放在郵箱中時,你可以確定郵差先生最終將郵件傳送給你的收件人。 在這個比喻中,RabbitMQ是郵政信箱,郵局和郵遞員。

RabbitMQ 和郵局的主要區別在於它不處理紙張,而是接受、儲存和轉發二進位制資料塊 - 訊息

RabbitMQ 和一般的訊息傳遞使用了一些術語。

  • Producing 意味著傳送。 A 程式是一個傳送訊息的生產者( producer):

    img

  • A queue( 佇列)是 RabbitMQ 中郵箱的名稱。 儘管訊息流經過 RabbitMQ 和您的應用程式,但它們只能儲存在佇列中。 一個佇列只受主機記憶體和磁碟限制的約束,它本質上是一個很大的訊息緩衝區。 許多生產者可以傳送進入一個佇列的訊息,並且許多消費者可以嘗試從一個佇列接收資料。 這就是我們代表佇列的方式:

    img

  • Consuming (消費) 類似於接受的意思。 消費者是一個等待接收訊息的主程式:

    img

請注意 producerconsumerbroker 不必駐留在同一主機上(實際上在大多數應用程式中也不會這麼做)。

"Hello World"

(使用 php-amqplib 客戶端)

​ 在本教程的這一部分,我們將使用PHP編寫兩個程式;一個傳送單個訊息的生產者,以及接收訊息並將其列印出來的消費者。我們將討論 php-amqplib API 中的一些細節,把注意力集中在這個簡單的事情上。這是一個訊息傳遞的 “Hello World”。在下圖中,P 是我們的生產者,C 是我們的消費者。中間的框是一個佇列—— RabbitMQ 代表消費者儲存的訊息緩衝區。

img

php-amqplib 庫

RabbitMQ 提供多種協議。本教程涵蓋了 AMQP 0-9-1,它是一種開放、通用的訊息傳遞協議。有許多不同語言的 RabbitMQ 客戶端。我們將在本教程中使用 php-amqplib ,並使用 Composer 進行依賴性管理。

Add a composer.json file to your project:

{
   "require": {
       "php-amqplib/php-amqplib": ">=2.6.1"
   }
}

如果您安裝了 Composer 並且功能正常,則可以執行以下操作:

composer.phar install

還有一個適用於 Windows 的 Composer 安裝程式。

現在我們安裝了 php-amqplib 庫,我們可以編寫一些程式碼。

Sending(傳送)

img

我們會呼叫我們的訊息釋出者(sender)send.php 和我們的訊息接收者 receive.php。 釋出者將連線到RabbitMQ,傳送一條訊息,然後退出。

send.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();

連線抽象出套接字連線(socket),併為我們處理協議版本協商和身份驗證等。在這裡,我們連線到本地機器上的代理 - 因此是 localhost。如果我們想連線到另一臺機器上的代理,我們只需在此指定其名稱或 IP 地址。

接下來我們建立一個頻道,這是大部分用於完成任務的 API 駐留的地方。

接下來是傳送,由於我們必須宣告一個佇列去為我們傳送,那麼我們可以將訊息釋出到佇列中:

$channel->queue_declare('hello', false, false, false, false);

$msg = new AMQPMessage('Hello World!');
$channel->basic_publish($msg, '', 'hello');

echo " [x] Sent 'Hello World!'\n";

宣告一個佇列是冪等的 - 只有當它不存在時才會被建立。訊息內容是一個位元組陣列,所以你可以輸入任何你喜歡的內容。

最後,我們關閉頻道和連線;

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

Here's the whole send.php class.

傳送不起作用!

如果這是你第一次使用 RabbitMQ,並且你沒有看到“已傳送”訊息,那麼你可能會抓住您的腦袋,想知道會出現什麼問題。 也許代理啟動時沒有足夠的可用磁碟空間(預設情況下它至少需要200 MB空閒空間),因此拒絕接受訊息。 檢查代理日誌檔案以確認並在必要時減少限制。配置檔案文件將告訴你如何設定 disk_free_limit。

Receiving(接收)

這是我們的消費者。我們將接收從 RabbitMQ 推送的訊息,因此與釋出單個訊息的釋出者不同,我們將持續執行以收聽訊息並將其列印出來。

img

程式碼內容(在 receive.php 中)與 send 有相同的包含和用法:

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

設定與釋出者相同; 我們開啟一個連線和一個通道,並宣告我們將要使用的佇列。 注意,這與傳送釋出的佇列匹配。

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

$channel->queue_declare('hello', false, false, false, false);

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

請注意,我們也在這裡宣告佇列。 因為我們可能會在釋出者之前啟動消費者,所以我們希望在我們嘗試使用訊息之前確保佇列已存在。

我們即將告訴伺服器將佇列中的訊息傳遞給我們。 我們將定義一個 PHP 可呼叫函式 ,它將接收伺服器傳送的訊息。 請記住,訊息是從伺服器非同步傳送到客戶端。

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

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

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

我們的程式碼會阻塞,而我們的回撥函式會傳遞收到的訊息。

Here's the whole receive.php class

把它們放在一起

現在我們可以執行這兩個指令碼。 在終端中,執行消費者(receiver):

php receive.php

然後執行釋出者(sender):

php send.php

消費者將列印它通過 RabbitMQ 從發件人獲得的訊息。 接收器將持續執行,等待訊息(使用Ctrl-C將其停止),因此請嘗試從其他終端執行傳送器。

佇列監聽

您可能希望看到 RabbitMQ 有什麼佇列以及它們中有多少條訊息。 您可以使用 rabbitmqctl 工具(作為特權使用者)執行此操作:

sudo rabbitmqctl list_queues

在 Windows 上,省略 sudo:

rabbitmqctl.bat list_queues

是時候轉到第2部分並構建一個簡單的工作佇列。

相關文章