rabbitmq php tutorial
Introduction RabbitMQ is a message broker. In essence, it accepts messages from producers , and delivers them to consumers . In-between, it can route, buffer, and persist the messages according to rules you give it. RabbitMQ 是一个消息代理
Introduction
RabbitMQ is a message broker. In essence, it accepts messages from producers, and delivers them to consumers. In-between, it can route, buffer, and persist the messages according to rules you give it.
RabbitMQ 是一个消息代理。说白了,它从“生产者”接收消息,并将这些消息发送给“消费者”。在这个过程中,它可以根据你给定的规则对消息进行路由、缓冲和持久化。
RabbitMQ, and messaging in general, uses some jargon.(常用术语)
-
Producing means nothing more than sending. A program that sends messages is a producer. We'll draw it like that, with "P":
- 生产无非就是发送。一个发送消息的程序就是一个“生产者”,我们用“P”来表示它。
-
-
A queue is the name for a mailbox. It lives inside RabbitMQ. Although messages flow through RabbitMQ and your applications, they can be stored only inside a queue. A queue is not bound by any limits, it can store as many messages as you like - it's essentially an infinite buffer. Many producers can send messages that go to one queue - many consumers can try to receive data from one queue. A queue will be drawn like this, with its name above it:
- 队列就像是邮箱的名字。它存于RabbitMQ内部。尽管消息流贯穿于RabbitMQ和你的应用,但它只能存储于队列当中。队列不受任何限制,随便你存多少消息,看你心情-队列本质上是一个无穷大的缓冲区。 多个“消费者”可以发送消息给一个队列-多个“消费者”也可以从一个队列接收消息。我们这样来表示一个队列(如下),上面是它的名字。
-
-
Consuming has a similar meaning to receiving. A consumer is a program that mostly waits to receive messages. On our drawings it's shown with "C":
- 消费意思就是接收。”消费者“通常是一个等待接受消息的程序。我们用“C”来表示。
-
Note that the producer, consumer, and broker do not have to reside on the same machine; indeed in most applications they don't.
注意:生产者、消费者和消息代理(中间人)不是必须在一个机器上,确实如此,大多数应用程序都这样。
"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.
在这一扒,我们会写俩PHP程序,一个发送单一消息的生产者,和一个接收消息并打印的消费者。我们略过一些php-amqplib API的细节,集中精力到这些简单的事儿上来开个头儿 —— 一个消息的Hello World程序。
In the diagram below, "P" is our producer and "C" is our consumer. The box in the middle is a queue - a message buffer that RabbitMQ keeps on behalf of the consumer.
在下面的图表中,P是我们的生产者,C是我们的消费者。中间内筐就是个队列-一个由RabbitMQ维持的消息缓冲区。
The php-amqplib client library
RabbitMQ speaks AMQP, which is an open, general-purpose protocol for messaging. There are a number of clients for AMQP in many different languages. We'll use the php-amqplib in this tutorial.
RabbitMQ 遵循AMQP——一个开放的、多用途的消息协议。还有若干不同语言的的AMQP客户端。我们就用php-amqplib啦~
Add a composer.json file to your project: 在你的项目中添加一个composer.json文件,内容如下:
{ "require": { "videlalvaro/php-amqplib": "v2.1.0" } }Provided you have composer installed, you can run the following: 假使你已经安装了composer, 有可以执行下面的命令:
$ composer.phar install
Now we have the php-amqplib installed, we can write some code.
现在php-amqplib安完了,写点code呗。
Sending(发送)
We'll call our message sender send.php and our message receiver receive.php. The sender will connect to RabbitMQ, send a single message, then exit.
创建一个文件send.php来发消息,receive.php来收消息。发送方(send.php)连接RabbitMQ发送一条消息,然后退出程序。
In send.php, we need to include the library and use the necessary classes:
send.php里,需要包含必要的库及引入必要的类。
require_once __DIR__ . '/vendor/autoload.php'; use PhpAmqpLib\Connection\AMQPConnection; use PhpAmqpLib\Message\AMQPMessage;
then we can create a connection to the server:
然后创建连接服务器的connection.
$connection = new AMQPConnection('localhost', 5672, 'guest', 'guest'); $channel = $connection->channel();
The connection abstracts the socket connection, and takes care of protocol version negotiation and authentication and so on for us. Here we connect to a broker on the local machine - hence the localhost. If we wanted to connect to a broker on a different machine we'd simply specify its name or IP address here.
这个连接帮我们做socket链接,处理协议版本谈判和鉴定。这样呢我们就链接到了本地的消息代理(broker),因为是localhost嘛。如果想链接不同机器上的broker,简单的指定下名字或者IP地址就好啦,就是替换一下上面的localhost。
Next we create a channel, which is where most of the API for getting things done resides.
下面我们创建个信道——多数API干的活都在这里完成。
To send, we must declare a queue for us to send to; then we can publish a message to the queue:
为了能发送消息,必须声明一个队列。然后就可以发送消息到了。
$channel->queue_declare('hello', false, false, false, false); $msg = new AMQPMessage('Hello World!'); $channel->basic_publish($msg, '', 'hello'); echo " [x] Sent 'Hello World!'\n";
Declaring a queue is idempotent - it will only be created if it doesn't exist already. The message content is a byte array, so you can encode whatever you like there.
声明队列是幂等的——只有在它不存在的情况下才会被创建。消息内容是字节数组,所以呢,你可以编码一下随便啥,放那替换下就能发。
Lastly, we close the channel and the connection;
末了,关闭信道和服务器连接。
$channel->close(); $connection->close();
Here's the whole send.php class. (这是整个send.php类文件)
Sending doesn't work!(发布出去消息咋办)
If this is your first time using RabbitMQ and you don't see the "Sent" message then you may be left scratching your head wondering what could be wrong. Maybe the broker was started without enough free disk space (by default it needs at least 1Gb free) and is therefore refusing to accept messages. Check the broker logfile to confirm and reduce the limit if necessary. The configuration file documentation will show you how to setdisk_free_limit.
如果你头一次用RabbitMQ并且没看到"已发送(sent)"字样的提示信息,然后剩下的就是挠头了——为毛呢?哪错了?有可能是broker启动时木有足够可用的硬盘空间(默认需要至少1G),所以拒绝接受消息。检查broker日志文件确定一下,有必要的话,调低下限值。这个配置文件会告诉你咋设置可用硬盘限值。
Receiving(接收消息)
That's it for our sender. Our receiver is pushed messages from RabbitMQ, so unlike the sender which publishes a single message, we'll keep it running to listen for messages and print them out.
发送者就是这么回事啦。接收者呢,顾名思义就是接收从RabbitMQ推送过来的消息,所以不像发送者哪有就发一条消息就完了。
我们保持接收者一直运行来接收和打印消息。
The code (in receive.php) has almost the same include and uses as send:
receive.php中include和use的代码几乎和send.php一样。
require_once __DIR__ . '/vendor/autoload.php'; use PhpAmqpLib\Connection\AMQPConnection;
Setting up is the same as the sender; 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.
设置也和上面一样,打开一个连接和信道,声明一个我们要消费(接收消息)的队列。注意这里要和上面发送者的的声明要对应。
$connection = new AMQPConnection('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 receiver before the sender, 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.
我们得告诉服务器从队列中给我们递送消息。定义个回调来接收服务器发送的消息。记住啊,消息从服务器发送到客户端是异步的啊。
$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.
由于$channel有回调,所以我们的代码会阻塞住(收听消息嘛,不是 bug哦),啥时候我们收到了消息,回调函数就会处理它啦。
Here's the whole receive.php class(完整的receive.php类文件)
Putting it all together(合体!!!)
Now we can run both scripts. In a terminal, run the sender:
写都写完了,跑一下呗,先跑sender
$ php send.php
then, run the receiver:然后跑receiver
$ php receive.php
The receiver 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.
内个,接收者会把从RabbitMQ接收的消息打印出来,当然这消息是发送者发给RabbitMQ的。接收者会在这死磕,一直跟这等消息(用Ctrl-C可以给干掉它),试试在其他的终端跑一下sender.
If you want to check on the queue, try using rabbitmqctl list_queues.
要想看看这个队列,用一下rabbitmqctl list_queues这个命令。(内个。。在sbin/下呢哦,找不到的话)
Hello World! 你好呀,世界~~
Time to move on to part 2 and build a simple work queue. (敬请期待,哦吼吼吼~~)
上一篇: 请好手谈谈关于php