(八)RabbitMQ消息队列-通过Topic主题模式分发消息
原文:(八)RabbitMQ消息队列-通过Topic主题模式分发消息
前两章我们讲了RabbitMQ的direct模式和fanout模式,本章介绍topic主题模式的应用。如果对direct模式下通过routingkey来匹配消息的模式已经有一定了解那fanout也很好理解。简单的可以理解成direct是通过routingkey精准匹配的,而topic是通过routingkey来模糊匹配。
在topic模式下支持两个特殊字符的匹配。
* (星号) 代表任意 一个单词
# (井号) 0个或者多个单词
注意:上面说的是单词不是字符。
如下图所示,RabbitMQ direct模式通过RoutingKey来精准匹配,RoutingKey为red的投递到Queue1,RoutingKey为black和white的投递到Queue2。
我们可以假设一个场景,我们要做一个日志模块来收集处理不同的日志,日志区分包含三个维度的标准:模块、日志紧急程度、日志重要程度。模块分为:red、black、white;紧急程度分为:critical、normal;把重要程度分为:medium、low、high在RoutingKey字段中我们把这三个维度通过两个“.“连接起来。
现在我们需要对black模块,紧急程度为critical,重要程度为high的日志分配到队列1打印到屏幕;对所以模块重要程度为high的日志和white紧急程度为critical的日志发送到队列2持久化到硬盘。如下示例:
RoutingKey为“black.critical.high”的日志会投递到queue1和queue2,。
RoutingKey为“red.critical.high”的日志会只投递到queue2。
RoutingKey为“white.critical.high”的日志会投递到queue2,并且虽然queue2的两个匹配规则都符合但只会向queue2投递一份。
新建topic.php用来发布三种routingkey的消息。
<?php
/*
* topic 模式
* create by superrd
*/
$exchangeName = 'extopic';
$routeKey1 = "black.critical.high";
$routeKey2 = "red.critical.high";
$routeKey3 = "white.critical.high";
$message1 = 'black-critical-high!';
$message2 = 'red-critical-high!';
$message3 = 'white-critical-high!';
$connection = new AMQPConnection(array('host' => '10.99.121.137', 'port' => '5672', 'vhost' => '/', 'login' => 'superrd', 'password' => 'superrd'));
$connection->connect() or die("Cannot connect to the broker!\n");
try {
$channel = new AMQPChannel($connection);
$exchange = new AMQPExchange($channel);
$exchange->setName($exchangeName);
$exchange->setType(AMQP_EX_TYPE_TOPIC);
$exchange->setFlags(AMQP_DURABLE);
$exchange->declareExchange();
$exchange->publish($message1,$routeKey1);
var_dump("[x] Sent ".$message1);
$exchange->publish($message2,$routeKey2);
var_dump("[x] Sent ".$message2);
$exchange->publish($message3,$routeKey3);
var_dump("[x] Sent ".$message3);
} catch (AMQPConnectionException $e) {
var_dump($e);
exit();
}
$connection->disconnect();
q1.php用来监听queue1队列:
<?php
/*
* topic 模式
* create by superrd
*/
$queueName = 'queue1';
$exchangeName = 'extopic';
$routeKey = "black.critical.high";
$connection = new AMQPConnection(array('host' => '10.99.121.137', 'port' => '5672', 'vhost' => '/', 'login' => 'superrd', 'password' => 'superrd'));
$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_TOPIC);
$exchange->setFlags(AMQP_DURABLE);
$exchange->declareExchange();
$queue = new AMQPQueue($channel);
$queue->setName($queueName);
$queue->setFlags(AMQP_DURABLE);
$queue->declareQueue();
$queue->bind($exchangeName, $routeKey);
//阻塞模式接收消息
echo "Message:\n";
while(True){
$queue->consume('processMessage');
//自动ACK应答
//$queue->consume('processMessage', AMQP_AUTOACK);
}
$conn->disconnect();
/*
* 消费回调函数
* 处理消息
*/
function processMessage($envelope, $q) {
$msg = $envelope->getBody();
echo $msg."\n"; //处理消息
$q->ack($envelope->getDeliveryTag()); //手动发送ACK应答
}
q2.php用来监听queue2队列:
<?php
/*
* topic 模式
* create by superrd
*/
$queueName = 'queue2';
$exchangeName = 'extopic';
$routeKey1 = "#.high";
$routeKey2 = "white.critical.*";
$connection = new AMQPConnection(array('host' => '10.99.121.137', 'port' => '5672', 'vhost' => '/', 'login' => 'superrd', 'password' => 'superrd'));
$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_TOPIC);
$exchange->setFlags(AMQP_DURABLE);
$exchange->declareExchange();
$queue = new AMQPQueue($channel);
$queue->setName($queueName);
$queue->setFlags(AMQP_DURABLE);
$queue->declareQueue();
$queue->bind($exchangeName, $routeKey1);
$queue->bind($exchangeName, $routeKey2);
//阻塞模式接收消息
echo "Message:\n";
while(True){
$queue->consume('processMessage');
//自动ACK应答
//$queue->consume('processMessage', AMQP_AUTOACK);
}
$conn->disconnect();
/*
* 消费回调函数
* 处理消息
*/
function processMessage($envelope, $q) {
$msg = $envelope->getBody();
echo $msg."\n"; //处理消息
$q->ack($envelope->getDeliveryTag()); //手动发送ACK应答
}
先运行q1.php和q2.php脚本保持订阅状态。然后执行topic.php脚本发布消息。q1和q2收到的消息如下:
如上截图,验证了我们之前的结论。
另外还有一些特殊情况例如:
- 如果binding_key 是 “#” - 它会接收所有的Message,不管routing_key是什么,就像是fanout
exchange。 - 如果 “*” and “#” 没有被使用,那么topic exchange就变成了direct exchange。
RabbitMQ技术交流QQ群:327034977(添加时请备注RabbitMQ)
(八)RabbitMQ消息队列-通过Topic主题模式分发消息的更多相关文章
- RabbitMQ消息队列(八)-通过Topic主题模式分发消息(.Net Core版)
前两章我们讲了RabbitMQ的direct模式和fanout模式,本章介绍topic主题模式的应用.如果对direct模式下通过routingkey来匹配消息的模式已经有一定了解那fanout也很好 ...
- (九)RabbitMQ消息队列-通过Headers模式分发消息
原文:(九)RabbitMQ消息队列-通过Headers模式分发消息 Headers类型的exchange使用的比较少,以至于官方文档貌似都没提到,它是忽略routingKey的一种路由方式.是使用H ...
- ActiveMQ之topic主题模式
开发环境我们使用的是ActiveMQ 5.11.1 Release的Windows版,官网最新版是ActiveMQ 5.12.0 Release,大家可以自行下载,下载地址.需要注意的是,开发时候,要 ...
- (转)RabbitMQ消息队列(四):分发到多Consumer(Publish/Subscribe)
上篇文章中,我们把每个Message都是deliver到某个Consumer.在这篇文章中,我们将会将同一个Message deliver到多个Consumer中.这个模式也被成为 "pub ...
- RabbitMQ消息队列(四):分发到多Consumer(Publish/Subscribe)
上篇文章中,我们把每个Message都是deliver到某个Consumer.在这篇文章中,我们将会将同一个Message deliver到多个Consumer中.这个模式也被成为 "pub ...
- RabbitMQ消息队列(四):分发到多Consumer(Publish/Subscribe)[转]
上篇文章中,我们把每个Message都是deliver(提供)到某个Consumer.在这篇文章中,我们将会将同一个Message deliver(提供)到多个Consumer中.这个模式也被成为 & ...
- 译: 5. RabbitMQ Spring AMQP 之 Topic 主题
在上一个教程中,我们提高了消息传递的灵活 我们使用direct交换而不是使用仅能够进行虚拟广播的fanout交换, 并且获得了基于路由key 有选择地接收消息的可能性. 虽然使用direct 交换改进 ...
- Azure Messaging-ServiceBus Messaging消息队列技术系列4-复杂对象消息是否需要支持序列化和消息持久化
在上一篇中,我们介绍了消息的顺序收发保证: Azure Messaging-ServiceBus Messaging消息队列技术系列3-消息顺序保证 在本文中我们主要介绍下复杂对象消息是否需要支持序列 ...
- 使用jedis实现Redis消息队列(MQ)的发布(publish)和消息监听(subscribe)
前言: 本文基于jedis 2.9.0.jar.commons-pool2-2.4.2.jar以及json-20160810.jar 其中jedis连接池需要依赖commons-pool2包,json ...
随机推荐
- Swift视频教程,Swift千人学iOS开发编程语言
此时大家站在同一起跑线.Swift语言将将是下一个风靡程序猿界的编程语言,是否能抢占先机,近在咫尺. 本期推荐Swift编程语言视频教程,内容包含:开发环境基本使用.数据类型和常量.数据自己主动检查和 ...
- GestureDetector- 滑屏手势方式实现
今天做的项目中,需要使用滑屏来调出一个界面,经过自己的尝试,结合网上的方法,成功实现了. 代码如下 package com.example.text; import android.app.Activ ...
- php课程 18-60 cookie和session的最主要区别是什么
php课程 18-60 cookie和session的最主要区别是什么 一.总结 一句话总结:存储位置不同:cookie存储在客户端:session存储在服务端. 1.cookie和session在p ...
- NPOI根据列索引获取列名
public static string ConvertColumnIndexToColumnName(int index) { index = index + ; ; ]; ; ) { int mo ...
- $.post()提交了数据,return不给跳转
本来Controller接到普通请求,return “somePage”,这样就跳转了.前台用$.post()提交了数据(不需要回调),我了个大草,return那里就不给跳转了这样怎么解决? ajax ...
- Linux 网卡驱动学习(九)(层二转发)
1.mac 地址表的自学习过程 port1上的A计算机要与port2上的B计算机通信时,A发到交换机上,交换机收到信息后,交换机先记录发port1所相应的a的mac地址并记录在自己的mac表中,然后再 ...
- textview-显示行数限制
在代码中直接添加 android:maxLines="2" android:ellipsize="end" 跟ellipsize搭配使用,超过两行的时候,第二行 ...
- js进阶 14 jquery的ajax有哪些函数和事件(多练)
js进阶 14 jquery的ajax有哪些函数和事件(多练) 一.总结 一句话总结:常用:load.ajax.post.get.getScript().getJSON().表单序列化,ajax事件这 ...
- 1.2 Use Cases中 Stream Processing官网剖析(博主推荐)
不多说,直接上干货! 一切来源于官网 http://kafka.apache.org/documentation/ Stream Processing 流处理 Many users of Kafka ...
- Php无限层级并显示层级数
今天在处理递归无限层级菜单时,遇到一个稍微烧脑的问题,如何显示当前节点所在的层级数.废话不多说,我们先看个直观的无限层级: <?php // 这里的arr是直接从数据库取出的,仅作为测试数据 $ ...