RabbitMQ 入门教程(PHP版) 第四部分:路由(Routing)
路由(Routing)
在前面的第三部分教程中,我们实现了一个简单的日志系统。可以把日志消息广播给多个接收者。
本篇教程中我们打算新增一个功能——使得它能够只订阅消息的一个字集。例如,我们只需要把严重的错误日志信息写入日志文件(存储到磁盘),但同时仍然把所有的日志信息输出到控制台中
绑定(Bindings)
前面的例子,我们已经创建过绑定(bindings),代码如下:
$exchange->publish($message, '');
绑定(binding)是指交换器(exchange)和队列(queue)的关系。可以简单理解为:这个队列(queue)对这个交换器(exchange)的消息感兴趣。
绑定的时候可以带上一个额外的routingkey参数。为了避免与basicpublish的参数混淆,我们把它叫做binding key。以下是如何创建一个带binding key的绑定。
$exchange->publish($message, $routeKey);
binding key的含义取决于交换器(exchange)的类型。我们之前使用过的fanout类型会忽略这个值。
Direct类型的交换器(exchange)
我们的日志系统广播所有的消息给所有的消费者(consumers)。我们打算扩展它,使其可以能够精确的过滤消息。例如我们也许值是希望当接收到一个严重的错误的时候才把消息写入磁盘,以免浪费磁盘空间。
我们使用的fanout类型的交换器(exchange)扩展性不够——它能做的仅仅是广播。
我们将会使用direct类型的交换器(exchange)来代替。路由的算法很简单——交换器将会对binding key和routing key进行精确匹配,从而确定消息该分发到哪个队列。
下图能够很好的描述这个场景:


在这个场景中,我们可以看到direct exchange X和两个队列绑定了。第一个队列使用orange作为binding key,第二个队列有两个绑定,一个使用black作为binding key,另外一个是green。
这样以来,当routing key为orange的消息发布到交换器(exchange),就会被路由到队列Q1。routing key为black或者green的消息就会路由到Q2。其他的所有消息都将会被丢弃。
多个绑定(Multiple bindings)


多个队列使用相同的binding key是合法的。我们的这个例子,我们可以添加一个X和Q1之间的绑定,使用blackbinding key。这样一来,direct交换器就和fanout交换器的行为一样,将会广播消息到所有匹配的队列。带有routing key为black的消息都会发送到Q1和Q2。
Emitting logs
我们将会发送消息到一个direct exchange,把日志级别作为routing key。这样子负责处理接收的脚本就可以选择它要处理的日志级别。我们先看看触发日志。
我们需要创建一个交换器(exchange):
$exchange->setName('direct_logs');
然后我们发送一则消息:
$exchange->publish($message, $severity);
我们先假设“severity”的值是info、warning、error中的一个。
订阅(Subscribing)
处理接收消息的方式和之前差不多,但是我们为每一个日志级别创建了一个新的绑定。
foreach ($severities as $item) {
$queue->bind($exchangeName, $item);
}
整合代码
emit_log_direct.php
<?php $severity = count($argv) > 2 ? $argv[1] : 'info';
$message = empty($argv[2]) ? 'Hello World!' : ' ' . $argv[2]; $connection = new AMQPConnection(array('host' => '127.0.0.1', 'port' => '5672', 'vhost' => '/', 'login' => 'guest', 'password' => 'guest'));
$connection->connect() or die("Cannot connect to the broker!\n"); $channel = new AMQPChannel($connection);
$exchange = new AMQPExchange($channel);
$exchange->setName('direct_logs');
$exchange->setType(AMQP_EX_TYPE_DIRECT);
//$exchange->declare();
$exchange->declareExchange(); $exchange->publish($message, $severity);
var_dump("[x] Sent $message"); $connection->disconnect();
receive_logs_direct.php
<?php
$exchangeName = 'direct_logs';
$connection = new AMQPConnection(array('host' => '127.0.0.1', 'port' => '5672', 'vhost' => '/', 'login' => 'guest', 'password' => 'guest'));
$connection->connect() or die("Cannot connect to the broker!\n");
$channel = new AMQPChannel($connection);
$exchange = new AMQPExchange($channel);
$exchange->setName($exchangeName);
$exchange->setType(AMQP_EX_TYPE_DIRECT);
//$exchange->declare();
$exchange->declareExchange();
$queue = new AMQPQueue($channel);
$queue->setFlags(AMQP_EXCLUSIVE);
//$queue->declare();
$queue->declareQueue();
$severities = $argv;
$file = $severities[0];
unset($severities[0]);
if (!$severities) {
var_dump("Usage:$file [info] [warning] [error]");
exit();
} else {
foreach ($severities as $item) {
$queue->bind($exchangeName, $item);
}
}
var_dump('[*] Waiting for messages. To exit press CTRL+C');
while (TRUE) {
$queue->consume('callback');
}
$connection->disconnect();
function callback($envelope, $queue) {
$msg = $envelope->getBody();
var_dump('[x]' . $envelope->getRoutingKey() . ':' . $msg);
$queue->nack($envelope->getDeliveryTag());
}
如果你希望只是保存warning和error级别的日志到磁盘,只需要打开控制台并输入:
php receive_logs_direct.php warning error > logs_from_rabbit.log
如果你希望所有的日志信息都输出到屏幕中,打开一个新的终端,然后输入:
php receive_logs_direct.php info warning error
[*] Waiting for logs. To exit press CTRL+C
如果要触发一个error级别的日志,只需要输入:
php emit_log_direct.php error "Run. Run. Or it will explode."
[x] Sent 'error':'Run. Run. Or it will explode.'
使用方法:先运行receive_logs_direct.php,后运行emit_log_direct.php
运行效果:

RabbitMQ 入门教程(PHP版) 第四部分:路由(Routing)的更多相关文章
- RabbitMQ官方中文入门教程(PHP版) 第四部分:路由(Routing)
路由(Routing) 在前面的教程中,我们实现了一个简单的日志系统.可以把日志消息广播给多个接收者. 本篇教程中我们打算新增一个功能——使得它能够只订阅消息的一个字集.例如,我们只需要把严重的错误日 ...
- RabbitMQ 入门教程(PHP版) 延迟队列,延迟任务
延迟任务应用场景 场景一:物联网系统经常会遇到向终端下发命令,如果命令一段时间没有应答,就需要设置成超时. 场景二:订单下单之后30分钟后,如果用户没有付钱,则系统自动取消订单. 场景三:过1分钟给新 ...
- RabbitMQ 入门教程(PHP版) 第三部分:发布/订阅(Publish/Subscribe)
发布/订阅 在上篇第二部分教程中,我们搭建了一个工作队列.每个任务之分发给一个工作者(worker).在本篇教程中,我们要做的之前完全不一样——分发一个消息给多个消费者(consumers).这种模式 ...
- RabbitMQ 入门教程(PHP版) 第二部分:工作队列(Work queues)
工作队列 在第一篇教程中,我们已经写了一个从已知队列中发送和获取消息的程序.在这篇教程中,我们将创建一个工作队列(Work Queue),它会发送一些耗时的任务给多个工作者(Works ). 工作队列 ...
- RabbitMQ 入门教程(PHP版) 第一部分:Hello World
abbitMQ是一个消息代理.它的核心原理非常简单:接收和发送消息.你可以把它想像成一个邮局:你把信件放入邮箱,邮递员就会把信件投递到你的收件人处.在这个比喻中,RabbitMQ是一个邮箱.邮局.邮递 ...
- RabbitMQ 入门教程(PHP版) 使用rabbitmq-delayed-message-exchange插件实现延迟功能
延迟任务应用场景 场景一:物联网系统经常会遇到向终端下发命令,如果命令一段时间没有应答,就需要设置成超时. 场景二:订单下单之后30分钟后,如果用户没有付钱,则系统自动取消订单. 场景三:过1分钟给新 ...
- RabbitMQ 入门教程(PHP版) 简单Demo
RabbitMQ的关键字说明 (1)Broker:经纪人.提供一种传输服务,维护一条从生产者到消费者的传输线路,保证消息数据能按照指定的方式传输.粗略的可以将图中的RabbitMQ Server当作B ...
- RabbitMQ 入门教程(PHP版) 第六部分:远程调用(RPC)
在云计算环境中,很多时候需要用它其他机器的计算资源,把一部分计算任务分配到其他节点来完成.RabbitMQ 如何使用 RPC 呢?下面将会通过其它节点完成斐波纳契示例. 流程图  当客户端启动时,它 ...
- 转 RabbitMQ 入门教程(PHP版) 使用rabbitmq-delayed-message-exchange插件实现延迟功能
延迟任务应用场景 场景一:物联网系统经常会遇到向终端下发命令,如果命令一段时间没有应答,就需要设置成超时. 场景二:订单下单之后30分钟后,如果用户没有付钱,则系统自动取消订单. 场景三:过1分钟给新 ...
随机推荐
- centos 环境下安装maven
安装Maven Maven的下载地址:http://maven.apache.org/download.cgi这里以最新的3.2.3版本为例进行安装,在这之前需要确保机器上已经安装了JDK. 首先下载 ...
- python 赋值与深浅拷贝
https://www.cnblogs.com/Eva-J/p/5534037.html
- Linux命令:awk求和、平均值、最大最小值
本文链接:https://blog.csdn.net/wyqwilliam/article/details/825600431.求和cat data|awk '{sum+=$1} END {print ...
- YAML_13 嵌套循环,循环添加多用户
with_nested ansible]# vim add1.yml --- - hosts: web2 remote_user: root vars: un: [a, b, c] ...
- 查看java的jar包源码
1.jd-gui (windows环境) 下载地址 https://files.cnblogs.com/files/indifferent/jd-gui-windows-1.5.1.zip 下载并解压 ...
- 检测 nginx 关闭切换keepalived
检测nginx 端口启用 关闭 keepalived 检测 nginx 进程:然后关闭 keepalived ,关闭漂移IP : cat nginx_pid.sh #!/bin/bash whil ...
- Cogs 452. Nim游戏!(博弈)
Nim游戏! ★ 输入文件:nim!.in 输出文件:nim!.out 简单对比 时间限制:1 s 内存限制:128 MB 甲,乙两个人玩Nim取石子游戏. nim游戏的规则是这样的:地上有n堆石子( ...
- Solution
小五的游戏 小碎骨的子集 芙兰朵露的框框 ⑨要求和
- 洛谷P1038 神经网络题解
注意如果是 \(if(c[i])\) 这条语句并没有说明c[i]不为负数,所以说最好老老实实的写 #include<cstdio> #define _ 0 using namespace ...
- BZOJ3551 Peaks加强版 [Kruskal重构树,主席树]
BZOJ 思路 我觉得这题可持久化线段树合并也可以做 我觉得这题建出最小生成树之后动态点分治+线段树也可以做 还是学习一下Kruskal重构树吧-- Kruskal重构树,就是在做最小生成树的时候,如 ...