# Hello World

> 原文：[Hello World](http://www.rabbitmq.com/tutorials/tutorial-one-php.html)\
> 翻译：小虾米（QQ:509129）\
> 参考：Ping Yang（Python版）

## 介绍

RabbitMQ是一个消息代理。它的核心原理非常简单：接收和发送消息。你可以把它想像成一个邮局：你把信件放入邮箱，邮递员就会把信件投递到你的收件人处。在这个比喻中，RabbitMQ就扮演着邮箱、邮局以及邮递员的角色。

RabbitMQ和邮局的主要区别是，它不是用来处理纸张的，它是用来接收、存储和发送消息（message）这种二进制数据的。

一般提到RabbitMQ和消息，都会用到一些专有名词。

* 生产(Producing)意思就是发送。发送消息的程序就是一个生产者(producer)。我们一般用"P"来表示:\
  ![](http://www.rabbitmq.com/img/tutorials/producer.png)
* 队列(queue)就是邮箱的名称。消息通过你的应用程序和RabbitMQ进行传输，它们能够只存储在一个队列（queue）中。 队列（queue）没有任何限制，你要存储多少消息都可以——基本上是一个无限的缓冲。多个生产者（producers）能够把消息发送给同一个队列，同样，多个消费者（consumers）也能够从同一个队列（queue）中获取数据。队列可以绘制成这样（图上是队列的名称）：\
  ![](http://www.rabbitmq.com/img/tutorials/queue.png)
* 消费（Consuming）和获取消息是一样的意思。一个消费者（consumer）就是一个等待获取消息的程序。我们把它绘制为"C"：\
  ![](http://www.rabbitmq.com/img/tutorials/consumer.png)

需要指出的是生产者、消费者、代理需不要待在同一个设备上；事实上大多数应用也确实不在会将他们放在一台机器上。

## Hello World!

**（使用php-amqplib客户端）**

在这部分的教程中我们将用PHP编写两个程序,生产者发送一个消息，消费者接收信息并打印出来。在使用[php-amqplib](https://github.com/php-amqplib/php-amqplib) API时我们会掩盖一些细节，把精力集中在这个非常简单的事情开始。这是一个“Hello World”的消息。

在下面的图中，“P”是我们的生产和“C”是我们的消费者。中间的框是一个队列 - 一个RabbitMQ保持代表消费者的消息缓冲区。

![](http://www.rabbitmq.com/img/tutorials/python-one-overall.png)

> #### php-amqplib客户端库
>
> RabbitMQ使用的是AMQP协议。要使用她你就必须需要一个使用同样协议的库。几乎所有的[编程语言](http://rabbitmq.com/devtools.html)都有可选择的库。PHP也是一样，我们将在本教程中使用**php-amqplib**，并且使用 [**Composer**](https://getcomposer.org/doc/00-intro.md)依赖管理：
>
> [php-amqplib](https://github.com/php-amqplib/php-amqplib)
>
> 在你的项目中添加一个 composer.json文件：
>
> ```
>   {
>      "require": {
>       "php-amqplib/php-amqplib": "2.6.1"
>      }
>  }
> ```
>
> 只要你已经安装[**Composer**](https://getcomposer.org/doc/00-intro.md)功能，你可以运行以下：
>
> ```
>    $ composer.phar install
> ```
>
> 这里是一个 [Composer Windows下的安装](https://github.com/composer/windows-setup)。

现在我们已经安装了php-amqplib库，我们可以写一些代码。

### 发送消息

![](http://www.rabbitmq.com/img/tutorials/sending.png)

我们将调用我们消息发送者 send.php，并调用我们的消息接收者 receive.php 。消息发送者将要连接RabbitMQ，发送一个消息，然后退出。

在[send.php](https://github.com/rabbitmq/rabbitmq-tutorials/blob/master/php/send.php)中，我们需要包含库和使用必要的类：

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

然后我们可以建立一个到RabbitMQ服务器的连接：

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

连接抽象的套接字连接，负责协议版本和身份验证等等。这里我们在本地机器上连接到一个代理 - 指定为localhost。如果我们想连接到另一台计算机上一个代理我们只需简单地指定其名称或IP地址。

接下来,我们创建一个通道,这是大部分的API来完成任务所在。

要发送，我们必须为我们发送声明一个队列，然后我们可以向队列发布消息：

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

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

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

声明一个队列是幂等的，它仅仅在不存在的情况下被创建。消息内容是一个字节数组，因此你可以编码成任意你喜欢的。

最后,我们关闭通道和连接;

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

[这是整个 send.php 源码](https://github.com/rabbitmq/rabbitmq-tutorials/blob/master/php/send.php)。

> 发送不成功！
>
> 如果这是你第一次使用RabbitMQ，并且没有看到“Sent”消息出现在屏幕上，你可能会抓耳挠腮不知所以。这也许是因为没有足够的磁盘空间给代理使用所造成的（代理默认需要1Gb的空闲空间），所以它才会拒绝接收消息。查看一下代理的日志确定并且减少必要的限制。[**配置文件文档**](http://www.rabbitmq.com/configure.html#config-items)会告诉你如何更改磁盘空间限制（**disk\_free\_limit**）。

### 获取数据

那是我们的发送者。我们的接受者获取从RabbitMQ推过来的消息，所以不像发送者发布一个消息，我们将保持运行监听消息并打印出来。

![](http://www.rabbitmq.com/img/tutorials/receiving.png)

代码（在 [receive.php](https://github.com/rabbitmq/rabbitmq-tutorials/blob/master/php/receive.php)）具有几乎相同的包括和加载：

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

设置和发送者是一样的，我们打开一个连接和一个通道，然后声明我们将要消耗的队列。请注意，这与发送的队列中的队列相匹配。

```php
$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回调](http://www.php.net/manual/en/language.types.callable.php)将接收服务器发送的消息。请记住，消息是从服务器异步发送到客户端的。

```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）将传递给接收的消息。

[这是整个 receive.php 源代码。](https://github.com/rabbitmq/rabbitmq-tutorials/blob/master/php/receive.php)

### 整合

现在就可以在终端中运行我们的程序了。启动发送者：

```
$ php send.php
```

然后启动消费者：

```
$ php receive.php
```

接收者将打印从发送者通过RabbitMQ发送的消息。接收器将继续运行，等待消息（使用Ctrl-C来中止），所以试着从另一个终端运行发件者。

> 列出队列（Listing queues）
>
> 如果你想查看Rabbitmq队列，并且想知道有多少消息存在其中，你(作为特权用户)可以使用rabbitmqctl 工具：

```
rabbitmqctl list_queues。
```

> 在Windows中，省略sudo：

```
rabbitmqctl.bat list_queues
```

是时候移步到[第二部分](https://rabbitmq.shujuwajue.com/tutorials_with_php/\[2]Work_Queues.md.html)了，我们将会建立一个简单的工作队列（work queue）。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://rabbitmq.shujuwajue.com/ying-yong-jiao-cheng/php-ban/1-hello_world.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
