发布订阅的应用场景通常为一个生产者、一个交换机,多个消费者各自创建队列绑定到交换机上订阅消息并消费。
发布订阅通常配合以下设置共同使用:
- 消费者创建的队列随机命名即可
- 关闭队列持久化
- 关闭消息持久化
- 消费者创建的队列在连接关闭时自动删除
- 开启自动消息确认
安装依赖
# composer.json
{
"require": {
"php-amqplib/php-amqplib": ">=3.0"
}
}
> composer.phar install
模式结构
在 RabbitMQ 消息传递模型中,生产者是不会向队列直接发送消息的,只能将消息发送给交换机。
交换机接收来自生产者的消息,然后将它们推送到队列中。
发布订阅使用的是fanout
交换机,这个交换机非常简单,将它收到的所有消息广播到它绑定的所有队列。
生产者
生产者连接到RabbitMQ,发送一条消息,然后退出。
# send.php
<?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();
// 定义一个名为 logs 的 fanout 广播交换机
$channel->exchange_declare('logs', 'fanout', false, false, false);
$data = implode(' ', array_slice($argv, 1));
if (empty($data)) {
$data = "info: Hello World!";
}
//
$msg = new AMQPMessage($data);
// 将消息发送到名为 logs 的 fanout 广播交换机 (消息内容, 交换机, 路由键);
$channel->basic_publish($msg, 'logs');
echo ' [x] Sent ', $data, "\n";
$channel->close();
$connection->close();
消费者
消费者监听来自RabbitMQ的消息,通常需要一直保持运行状态以监听消息。
# receive.php
<?php
require_once __DIR__ . '/vendor/autoload.php';
use PhpAmqpLib\Connection\AMQPStreamConnection;
// 创建连接
$connection = new AMQPStreamConnection('localhost', 5672, 'guest', 'guest');
// 创建通道
$channel = $connection->channel();
// 定义一个名为 logs 的 fanout 广播交换机
$channel->exchange_declare('logs', 'fanout', false, false, false);
// 创建一个随机命名的新队列,第三个参数为关闭队列持久化,第四个参数为当声明它的连接关闭时队列会被自动删除
list($queue_name, ,) = $channel->queue_declare("", false, false, true, false);
// 将随机命名的队列绑定到 fanout 广播交换机,生产者向交换机发送消息将被广播到绑定的队列中
$channel->queue_bind($queue_name, 'logs');
echo " [*] Waiting for messages. To exit press CTRL+C\n";
// 定义回调函数
$callback = function ($msg) {
echo ' [x] ', $msg->body, "\n";
};
// 第四个参数设为true开启自动消息确认,即投递消息后立刻标记为删除
$channel->basic_consume($queue_name, '', false, true, false, false, $callback);
while ($channel->is_open()) {
$channel->wait();
}
$channel->close();
$connection->close();
运行
打开一个终端,运行消费者,将日志放到文件中:
php receive.php > logs_from_rabbit.log
打开另一个终端,运行消费者,将日志输出到终端:
php receive.php
# => [*] Waiting for messages. To exit press CTRL+C
# => [x] Received 'Second message..'
# => [x] Received 'Fourth message....'
打开另一个终端,运行生产者:
php send.php
查看所有交换机
sudo rabbitmqctl list_exchanges
查看所有的绑定关系
sudo rabbitmqctl list_bindings
# => Listing bindings ...
# => logs exchange amq.gen-JzTY20BRgKO-HjmUJj0wLg queue []
# => logs exchange amq.gen-vso0PVvyiRIL2WoV3i48Yg queue []
# => ...done.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。