(八)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 ...
随机推荐
- 【Codeforces Round #457 (Div. 2) A】 Jamie and Alarm Snooze
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 暴力往前走x分钟就好. 直到出现7为止. [代码] #include <bits/stdc++.h> using nam ...
- bitset也挺好用的
http://www.cplusplus.com/reference/bitset/bitset/bitset/ std::bitset<16> foo; std::bitset<4 ...
- Centos6.4安装opennebula
Centos6.4安装opennebula #安装163源 http://mirrors.163.com/.help/CentOS6-Base-163.repo #安装epel源 wget http: ...
- eclipse - 下载网址
这里面有着非常齐全的eclipse相关资源,而且都是放在网盘里面的,下载也方便 http://www.androiddevtools.cn/
- Qt之界面换肤
简述 常用的软件基本都有换肤功能,例如:QQ.360.迅雷等.换肤其实很简单,并没有想象中那么难,利用前面分享过的QSS系列文章,沃我们完全可以实现各种样式的定制! 简述 实现原理 效果 新建QSS文 ...
- Git安装及密钥的生成并上传本地文件到GitHub上
之前用的GitHub,不太熟练,一直在上传的过程中遇到了一些问题,看了网上诸多教程,总觉得很乱,特参考一些资料,总结了一篇完整的操作步骤,从下载安装到上传文件,亲测有效 1.下载Git软件:https ...
- 洛谷 P1795 无穷的序列_NOI导刊2010提高(05)
P1795 无穷的序列_NOI导刊2010提高(05) 题目描述 有一个无穷序列如下: 110100100010000100000… 请你找出这个无穷序列中指定位置上的数字 输入输出格式 输入格式: ...
- 关于C++中的内存泄露
1.c++内存泄漏的定义: 内存泄漏(memory leak)是指由于疏忽或错误造成了程序未能释放掉不再使用的内存的情况.内存泄漏并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,失 ...
- Android Service com.android.exchange.ExchangeService has leaked ServiceConnection
启动Android项目的时候,clean Project的时候,报错: android.app.ServiceConnectionLeaked: Service com.android.exchan ...
- hibernate 注解配置<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/X
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.sp ...