RabbitMQ(3):hello-world

介绍

RabbitMQ是一个消息代理器: 它接受和转发消息。你可以把它当作一个邮局: 当你把你的邮件放到邮箱里的时候, 你可以肯定邮差最终会把你的邮件交给你邮件上的收件人。在这个比喻中, RabbitMQ扮演的就是这个邮箱、邮局和邮差的角色。

RabbitMQ和邮局之间的主要区别是,它不处理纸质邮件,而是接受,存储和转发二进制数据——消息。

RabbitMQ和一般的消息传递,有一些专业术语:

生产者(Producing)的工作就是发送消息。生产者是一个发送消息的程序:

RabbitMQ包含一个队列,这个队列起类似邮箱的作用。虽然消息经过RabbitMQ和应用程序,但是他们只可以被存储在队列中。队列只受主机内存和磁盘的限制,它本质上是一个很大的消息缓冲区。生产者可以将消息发送到队列,然后消费者可以从队列接收消息。下图是我们如何表示一个队列:

消费者的工作就是接收消息。消费者是一个等待接收消息的程序。

注意:生产者,消费者和消息代理可以不再同一台主机上;一个应用程序可以既是生产者也是消费者。

“Hello World”

(using the php-amqplib Client)

In this part of the tutorial we’ll write two programs in PHP; a producer that sends a single message, and a consumer that receives messages and prints them out. We’ll gloss over some of the detail in the php-amqplib API, concentrating on this very simple thing just to get started. It’s a “Hello World” of messaging.

在下图中,“P”是我们的生产者,“C”是我们的消费者。中间的方框是一个缓存消息的队列。

The php-amqplib client library

RabbitMQ应用了很多协议。这个实例中包含了AMQP 0-9-1,这是一个以开源,通用为设计目的的消息协议。RabbitMQ有很多用不同语言实现的客户端。在这个实例中我们将使用php-amqplib,并且用Composer来管理依赖。

在你的项目中添加一个 composer.json 文件:

1
2
3
4
5
{
"require": {
"php-amqplib/php-amqplib": ">=2.6.1"
}
}

如何你之前没有安装Composer,你可以使用下面的命令进行安装。

1
yum install composer

安装好Composer之后,执行一下下面的命令来添加依赖。

1
composer install

现在,我们的php-ampqlib库已经装好了,我们可以开始写代码了。

Sending

我们将生产者命名为 send.php,将消费者命名为 receive.php。生产者将连接RabbitMQ,发送一条消息,然后退出。

send.php 中, 我们需要导入类库并使用use引入必须的类:

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

然后我们创建一个连接服务器的Connection:

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

这个连接抽象了socket连接,并且替我们完成协议版本确认和授权的工作。这里我们适用localhost连接到了本地的一个消息代理。如果我们想要连接到其他机器的消息代理上,我们只需要修改一下IP地址。

接下来我们初始化一个信道,在rabbitmq中大部分的API操作都集中于信道这个位置。

发送消息前,我们必须定义一个队列,然后我们将一个消息发送到这个队列上。

1
2
3
4
5
6
$channel->queue_declare('hello', false, false, false, false);

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

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

这里建议每次发送消息前都定义一下队列,虽然如果之前同一个名字的队列已经创建过就不会创建了,但是为了防止因为没有创建队列而出错,最好养成每次使用前创建队列的习惯。消息的内容是以字节数组的形式发送的,所以这里你可以用任何一种编码方式发送消息。

最后,我们需要关闭信道和服务器连接。

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

Here’s the whole send.php class.

Receiving

消息生产者只发送一条消息,而消息消费者需要不断的处理从RabbitMQ发来的消息,所以,我们需要保持消息消费者始终处于监听状态,并将收到的消息打印出来。

The code (in receive.php) has almost the same include and uses as send:

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

Setting up is the same as the publisher; we open a connection and a channel, and declare the queue from which we’re going to consume. Note this matches up with the queue that send publishes to.

1
2
3
4
5
6
$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";

Note that we declare the queue here, as well. Because we might start the consumer before the publisher, we want to make sure the queue exists before we try to consume messages from it.

We’re about to tell the server to deliver us the messages from the queue. We will define a PHP callable that will receive the messages sent by the server. Keep in mind that messages are sent asynchronously from the server to the clients.

1
2
3
4
5
6
7
8
9
$callback = function ($msg) {
echo ' [x] Received ', $msg->body, "\n";
};

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

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

Our code will block while our $channel has callbacks. Whenever we receive a message our $callback function will be passed the received message.

Here’s the whole receive.php class

Putting it all together

Now we can run both scripts. In a terminal, run the consumer (receiver):

1
php receive.php

then, run the publisher (sender):

1
php send.php

The consumer will print the message it gets from the sender via RabbitMQ. The receiver will keep running, waiting for messages (Use Ctrl-C to stop it), so try running the sender from another terminal.

Listing queues

You may wish to see what queues RabbitMQ has and how many messages are in them. You can do it (as a privileged user) using the rabbitmqctl tool:

1
sudo rabbitmqctl list_queues

官网原文:http://www.rabbitmq.com/tutorials/tutorial-one-php.html