php实战RabbitMQ五(发布与订阅)

php实战RabbitMQ五(发布与订阅)

  • 前言
  • 原理
  • 解析
  • 交换机类型
  • 消息生产者
    • 初始化交换机
    • 消息发布--代码
  • 消息接收者
    • 初始化队列
    • 消息订阅--代码
  • 运行效果

前言

在生活中发布与订阅是我们时常遇到的事情,比如手机上每天到来的通知。今天我们来实现这一程序。

原理

通过改变交换机的模式与设置临时队列完成

解析

  1. 我们需要消息发布者程序
  2. 还需要消息订阅者程序
  3. 消息接收者在关注了发布者程序后,发布者程序推送最新内容。所以接收者对之前的内容不关心。
  4. 消息发布者只需将消息发布到交换机,消息接收者连接对应交换机,声明队列获取消息。
  5. 当消费者要退出后,这个队列也没有必要存在,需要销毁。

交换机类型

为了完成发布与订阅,有必要了解rabbitMQ的交换机类型,如下:

  1. fanout 交换机获取到绑定队列,不再判断路由键,将消息分发到队列中。
  2. direct 交换机获取到绑定队列,判断是否完全匹配路由键,发送到匹配的队列中。
  3. topic 交换机获取到绑定队列,判断是否完全匹配路由键与绑定键,发送到匹配的队列中。
  4. headers 再绑定队列与交换机时设置键值对,发送消息时获取消息中的headers 判断是否存在此键值对,成功则发送。

通过了解,发现fanout适合做消息发布与订阅。

消息生产者

注意生产者无需将初始化队列

初始化交换机

生产者代码与之前的内容大同小异,在初始化交换机部分,将其类型设置为fanout

$channel->exchange_declare('mq_sms_send_ex3', AMQPExchangeType::FANOUT, false, false, false); 

消息发布–代码

<?php 
require_once __DIR__ . '/vendor/autoload.php';
use PhpAmqpLib\Connection\AMQPStreamConnection;
use PhpAmqpLib\Exchange\AMQPExchangeType;
use PhpAmqpLib\Message\AMQPMessage;


//获取终端提示用户输入的数据
fwrite(STDOUT, "Please enter a message:\n");
$msg_str = fgets(STDIN);

//建立生产者与mq之间的连接    
//参数:地址,端口,账号,密码
$connection = new AMQPStreamConnection('localhost', 5672, 'guest', 'guest');

//在已连接基础上建立生产者与mq之间的通道
$channel = $connection->channel();

//声明初始化交换机   
//参数:交换机名,路由类型,是否检测同名队列,是否开启队列持久化,通道关闭后是否删除队列
$channel->exchange_declare('mq_sms_send_ex3', AMQPExchangeType::FANOUT, false, false, false); 


//生成消息
$msg = new AMQPMessage($msg_str);

//推送消息到某个交换机
//参数:消息,交换机名,路由键名
$channel->basic_publish($msg, 'mq_sms_send_ex3');
echo " [x] Sent: $msg_str \n";

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

消息接收者

消息接收者需要初始化队列,接受消息 (队列名最好随机,不重复,这样每开一个接收者,都是全新客户端)。

初始化队列

list($queue_name, ,) = $channel->queue_declare("", false, false, true, false);

$queue_name 便是队列的名字
第四个参数设置为true,独占队列,关闭连接,队列将被删除。

消息订阅–代码

<?php 
require_once __DIR__ . '/vendor/autoload.php';
use PhpAmqpLib\Connection\AMQPStreamConnection;
use PhpAmqpLib\Exchange\AMQPExchangeType;

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

//声明初始化交换机   
//参数:交换机名,路由类型,是否检测同名队列,是否开启队列持久化,通道关闭后是否删除队列
$channel->exchange_declare('mq_sms_send_ex3', AMQPExchangeType::FANOUT, false, false, false);

//声明初始化一条队列
//参数:队列名,是否检测同名队列,是否开启队列持久化,是否能被其他队列访问,通道关闭后是否删除队列
list($queue_name, ,) = $channel->queue_declare("", false, false, true, false);

//将队列与某个交换机进行绑定,并使用路由关键字
//参数:队列名,交换机名,路由键名
$channel->queue_bind($queue_name, 'mq_sms_send_ex3');

echo ' [*] Waiting for messages', "\n";

$callback = function($msg) {
     
  echo " [x] Received ", $msg->body, "\n";

  //判断获取到quit后
  if (trim($msg->body) == 'quit') {
     
  	
        $msg->getChannel()->basic_cancel($msg->getConsumerTag());
    }

};

$channel->basic_qos(null, 1, null);

//
//参数:队列名,消费者标识符,不接收此使用者发布的消息,使用者是否使用自动确认模式,请求独占使用者访问,不等待,消息回调函数
$channel->basic_consume($queue_name, 'consumer1', false, true, false, false, $callback);


function shutdown($channel, $connection)
{
     
    $channel->close();
    $connection->close();
}

register_shutdown_function('shutdown', $channel, $connection);

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

运行效果

php实战RabbitMQ五(发布与订阅)_第1张图片
可以看到代码运行后生成的两个队列
php实战RabbitMQ五(发布与订阅)_第2张图片

你可能感兴趣的:(php,rabbitmq)