RabbitMQ tutorial-one-php

簡介

RabbitMQ 是一個 message broker: 它接收並轉發消息。可以把它想象爲一個郵局:你把信件放到郵箱裏面,信件最終會被郵遞員投送到目的地。類比的講,RabbitMQ就是一個郵箱,一個郵局,一個郵遞員。
RabbitMQ與郵局最大的不同是它並不處理紙質對象,它接收,儲存並轉發二進制數據塊,也就是消息(messages)。
RabbitMQ和一般消息傳遞,有很專業術語。

  • 生產意味着僅僅發送消息,專門用來發送消息的程序叫做生產者。
    在這裏插入圖片描述
  • 隊列是RabbitMQ裏面的一個模塊,像郵箱一樣。儘管消息流在RabbitMQ和你的應用中傳遞,但是消息流僅僅只能保存在一個隊列中。一個隊列僅僅受限於服務端的內存和硬盤限制,它本質上是一個消息緩存;多個生產者可以發送消息到一個隊列,多個消費者也可以從一個隊列中接收消息。
    在這裏插入圖片描述
  • 消費和接收差不多,消費者程序要做的就是等待和接收消息;
    在這裏插入圖片描述
    需要注意的是,生產者,消費者和RabbitMQ並不是部署在同一臺服務器上的。事實上,很多應用都不是部署在同一側的。並且同時,一個應用可以同時是生產者,並且同時即是消費者。

“Hello World”

(using the php-amqplib Client)

在這段教程裏面我們會用PHP寫兩段程序,一個生產者發送簡單的消息,一個消費者接收消息並把他們打印出來。我們主要去實現hello world的發送和接收,不會太多探討php-amqplibAPI的細節。
在下面簡圖中,P是生產者,C是消費者。中間的是消息隊列,是RabbitMQ針對消費者保持的一個消息緩存。
在這裏插入圖片描述
PHP裏面使用composer導入php-amqplib/php-amqplib類庫。
在composer.json裏面加入

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

執行導入

composer.phar install

導入類庫之後,我們就可以編寫代碼了。

Sending

在這裏插入圖片描述
設置消息發送爲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連接,並且處理了底層協議等。這裏我們連接的是本地的RabbitMQ,如果想要連接別的RabbitMQ,只需要更換ip即可。
下面我們創建一個channel,channel是大多數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();

send.php完整代碼

Receiving

消費者監聽RabbitMQ的message,不像生產者一樣僅僅發送一條消息,我們讓消費者一直監聽消息隊列,然後把消息打印出來。
在這裏插入圖片描述
首先像生產者一樣加載類庫。

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

建立和生產者一樣,我們開啓一個連接和一個channel,並且聲明一個要消費的隊列。隊列要和生產者隊列一樣。

$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();
}

只要channel有callback閉包函數,程序會阻塞。當從服務端接收一個消息之後,callback閉包函數會接收到消息。
receive.php完整代碼

Putting it all together

同時運行兩個腳本。
運行消費者

php receive.php

運行生產者

php send.php

消費者會打印出他從RabbitMQ接收到的所有消息。消費者會一直運行等待消費消息。

監聽隊列
如果想看到RabbitMQ的隊列列表,並查看裏面有多少條消息,可以使用rabbitmqctl工具查看。

sudo rabbitmqctl list_queues

在windows可以這樣查看

rabbitmqctl.bat list_queues

官方鏈接:https://www.rabbitmq.com/tutorials/tutorial-one-php.html

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