php实战RabbitMQ七(路由键之日志管理案例二topic)

本文通过PHP与RabbitMQ结合,展示了如何使用Topic交换机来灵活管理不同来源的日志,如email.*和*.error,实现高效的一站式错误和邮件日志收集。生产者根据路由键动态发送消息,消费者则根据绑定规则接收并处理。
摘要由CSDN通过智能技术生成

序言

在上一章通过直接(direct)交换机实现了有选择性接收日志。本章将使用话题(topic)交换机完成更复杂的消息管理。

当你读到这一章,emmmmm,还记的交换机的四种类型吗?

需求分析

上一章日志管理很笼统,它不能详细区分日志来源,对不同来源的日志进行指定处理。

面临问题

不同来源的日志…la么多,怎么处理?
有同学大喊:多少个来源分多少个队列?emmm,晕
可能你要收集的日志来源少,那我再加点需求。
如果多个来源,我还想获取关于error的所有日志,无论来自哪里,统一收集。
那么你要初始化n个队列吗?

解决办法

使用话题(topic)交换机可以很轻松完成这一需求。

举个大栗子:
我的所有 我的什么呢?我拥有的都算进来
谁的自行车 谁呢的? emmmm 谁的都可以吧
大栗子对应程序:
email.* 邮件日志的所有 所有的邮件日志都要管理了
*.error 所有日志的error 出现error的日志都要管理了

topic介绍

topic通过判断绑定键与路由键是否匹配,但是这里的路由键只需要模糊匹配即可。

模糊路由键中允许出现* # 来模糊匹配,多个单词之间使用.隔开。

* 可以代替一个词。
# 可以代替零个或更多的单词。

上面的大栗子看懂了吧~~~
email.* 可表示 email.info email.error email.lalala
*.error 可表示 nginx.error mysql.error lalala.error
# 可表示接收一切

注意:

  1. 如果时路由键没有匹配到任何绑定键,它将被丢弃。
  2. 消息只会被发往同一个队列一次,不会因为路由键与多个绑定键都匹配发送多次。

生产者

完整源码

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

//这里作者使用php7版本
$routing_key = $argv[1] ?? 'info';

//获取终端提示用户输入的数据
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_ex5', AMQPExchangeType::TOPIC, false, false, false); 


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

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

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


消费者

在上一章基础上只修改了交换机类型。

核心代码

$channel->exchange_declare('mq_sms_send_ex5', AMQPExchangeType::TOPIC, false, false, false);

完整源码

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

//这里作者使用php7版本
$routing_keys = $argv[1] ? array_slice($argv, 1) : ['info', 'warn', 'error'];

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

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

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

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

}

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();
}

运行效果

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小猴子喝牛奶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值