RabbitMQ译文 — 简单的开始(Hello World!)
一、简介
RabbitMQ 是一个消息代理:它接收并转发消息。你能把它想象成一个邮局:当你把一封想要邮寄的信件放到一个邮箱里的时候,你能确定邮递员最终一定会把你的这封信递交给你的收信人。以此来比喻,RabbitMQ就是一个邮箱,一个邮局和一个邮递员。
RabbitMQ和邮局之间最大的不同是RabbitMQ不处理纸质邮件,而是接收,存储和转发二进制数据——消息。
通常,RabbitMQ 和消息使用一些术语。
生产(producing):也就是发送,一个程序发送消息就是生产者。
队列(queue):一个队列好比是一个寄宿在RabbitMQ内的邮箱,尽管消息流转于RabbitMQ和你的应用之间,但它们仅被存储在一个队列中。一个队列仅由主机内存和磁盘限额所限制,它本质上就是一个大的消息缓冲区。许多生产者能发送消息到某一个队列中,许多消费者尝试从某队列中接收消息数据。我们这样来表示一个队列:
消费(consuming):消费和接收具有类似的意义,一个消费者通常就是一个程序来等待接收消息:
需要说的是生产者,消费者和代理不必都位于同一台主机上,实际上在大多数的应用中他们也没有这么做。
二、"Hello World"
(使用 php-amqplib 客户端)
在这部分教程中,我们将用PHP写两段程序;一个发送单一消息的生产者和一个接收消息并打印出来的消费者。为了有个好的开始,我们先不讨论php-amqplib API的详细信息,而专注于这件简单的事情。就是一条“Hello World”的信息。
在下面的图示中,“P”是我们的生产者,“C”是我们的消费者。中间的盒子就是一个队列——一个RabbitMQ为了消费者保存消息的缓冲区。
php-amqplib 客户端类库
RabbitMQ支持多种协议,本教程使用AMQP 0-9-1,这是一个针对消息的开放的,通用的协议。对于RabbitMQ有很多不同语言的客户端。在教程里我们将使用php-amqplib客户端,并用Composer来管理相关依赖。
添加一个composer.json文件到你的项目里:
{ "require": { "php-amqplib/php-amqplib": ">=2.6.1" } }
假如你已经安装了Composer和相关功能,你能运行下面的:
composer.phar install这里有一个Windows系统的Composer安装文件。
现在我们已经安装了php-amqplib类库,我们可以写一些代码了。
发送
我们将调用我们的消息发布者(发送者)send.php 和我们的消息接收者 receive.php。这个发布者将连接RabbitMQ,发送一条消息后退出。
在send.php,我们需要包括类库并 use 必要的类。
require_once __DIR__ . '/vendor/autoload.php';
use PhpAmqpLib\Connection\AMQPStreamConnection;
use PhpAmqpLib\Message\AMQPMessage;
然后我们就可以建立一个到服务器的连接:
$connection = new AMQPStreamConnection('localhost', 5672, 'guest', 'guest');
$channel = $connection->channel();
这个连接抽象于套接字连接,为我们负责协议版本的协商和认证等等。从 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();
发送不成功!
如果这是你第一次使用RabbitMQ并且没有看到发送的信息,那么你可能会挠着头在想什么地方弄错了。也许是代理被启动而没有足够的磁盘空间(默认需要至少200MB的剩余空间)而拒绝接收消息。要在必要时检查代理的日志文件确认并减少限制。配置文件文档会告诉你怎样设置disk_free_limit。
接收
这就是我们的发布者。我们的接收者被推送来自于RabbitMQ的消息,因此不像发布者那样发布消息,我们将保持它运行并监听消息而后打印它们。
receive.php 里的代码有和发送相同的包含和用法:
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 callable 用来接收来自服务器发送的消息。记住消息被异步的从服务器发送至客户端。
$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函数将被传递这条被接收的消息。
把它放在一起
现在我们能够运行这两个脚本。在终端运行消费者(接收者):
php receive.php
然后运行发布者(发送者):
php send.php
消费者将打印它通过RabbitMQ中获得的消息。接收者将保持运行,等候消息(使用 Ctrl-C 结束),因此试着在另一个终端运行第二个发送者。
列出队列
你可能想要看RabbitMQ已有的队列和在这些队列中有多少条消息。你(有权限的用户)能使用rabbitmqctl工具实现。
sudo rabbitmqctl list_queues在windows系统下,省略sudo:
rabbitmqctl.bat list_queues
在下一课,我们将建立一个简单的工作队列。