转载RabbitMQ入门(5)--主题
主题(topic)
(使用Java客户端)
在先前的指南中我们改进了我们的日志系统。取代使用fanout类型的交易所,那个仅仅有能力实现哑的广播,我们使用一个direct类型的交易所,获得一个可以有选择性的接收日志。
虽然使用direct交易所类型已经改善了我们的系统,但它依旧有限制-它不能根据多个条件进行路由。
我们的日志系统中,我们可能想要订阅不仅仅基于严格的日志,同样基于发布日志的源码。你可能了解到syslog unix tool的概念,那个基于严格的(info/warn/crit…)和灵巧的(auth/cron/kern…)路由日志。
那个将会给我们许多灵活性-我们可能仅仅想监听来自于cron的关键性的错误和所有来自于kern的日志。
为了在我们日志系统中实现那个,我们需要学习更复杂的topic类型交易所。
topic类型交易所
发送到topic类型的交易所不能有任意的路由的关键字-它必须是一个关键字列表,由点分隔。这关键字可以是任意的,但 是通常可以说明消息的基本的联系。几个合法的路由关键字例 子:“stock.usd.nyse”,“nyse.vmw”,“quick.orange.rabbit”。可能有很多你想要的路由关键字,上限是 255个字节。
这绑定关键字必须也在这同样的表单里。topic交易所逻辑背后是与direct交易所类型类似-一个带特别的路由关键字的消息将会被传递到所有匹配绑定的关键字的队列。但是有两个特别重要的绑定关键字。
>* (星标) 能替代任意一个单词。
># (哈希) 能代替零个或多个单词。
这个例子中是很容易解释的: 
在这个例子中,我们发送的消息都描述的是动物。被发送的消息的路由关键字是由三个单词(两个点)组成。路由关键字中第一个单词描述的是速度,第二个描述的是颜色,第三个是物种:
“<速度>.<颜色>.<物种>“。
我们创建了三个绑定:Q1s是由绑定关键字”。orange.“所约束,Q2由”。。rabbit"和"lazy.#“所约束。
这些绑定可以概括为:
>Q1 是对
orange颜色的动物感兴趣。
>Q2 想了解关于兔子的所有信息和所有慢吞吞的动物信息。
一个路由关键字为"quick.orange.rabbit"消息将会被传递到所有队列。消息"lazy.orange.elephant"同样也
传递到所有队列。另一方面"quick.orange.fox"仅进入第一队列,“lazy.brown.fox"仅进入第二个队列。
“lazy.pink.rabbit"仅传递到第二个队列一次,即使它会匹配两个绑定。“quick.brown.fox"不符合任何绑定关键字,所以会
被丢弃。
如果我们打破我们的约定,发送一个消息带一个或四个单词的关键字,像"orange"或"quick.orange.male.rabbit”,会发生什么呢?好吧,这些消息不会匹配任何绑定,将会丢失。
另一方面"lazy.orange.male.rabbit”,即使它有四个单词,将会匹配最最后那个绑定,将消息传递到第二个队列。
topic类型交易所topic类型交易所是强大的,能表现的像其他的交易所。
Topic exchange is powerful and can behave like other exchanges.
当一个队列绑定到了”#“(哈希)绑定关键字-它会接收所有消息,不管路由关键字是什么-类似于fanout类型交易所
当topic类型交易所中没有使用像”*“(星标)和”#“(哈希)的特殊字符,它的行为类似于direct类型交易所
把所有放在一起
我们将会在我们的日志系统中使用topic类型交易所。我们假设我们的工作的日志消息的路由关键字是由两个单词组成,格式为:“ . “。
这代码和先前的几乎一样:
EmitLogTopic.java的代码:
public class EmitLogTopic {
private static final String EXCHANGE_NAME = "topic_logs";
public static void main(String[] argv)
throws Exception {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
channel.exchangeDeclare(EXCHANGE_NAME, "topic");
String routingKey = getRouting(argv);
String message = getMessage(argv);
channel.basicPublish(EXCHANGE_NAME, routingKey, null, message.getBytes());
System.out.println(" [x] Sent '" + routingKey + "':'" + message + "'");
connection.close();
}
//...
}
ReceiveLogsTopic.java的代码:
public class ReceiveLogsTopic {
private static final String EXCHANGE_NAME = "topic_logs";
public static void main(String[] argv)
throws Exception {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
channel.exchangeDeclare(EXCHANGE_NAME, "topic");
String queueName = channel.queueDeclare().getQueue();
if (argv.length < 1){
System.err.println("Usage: ReceiveLogsTopic [binding_key]...");
System.exit(1);
}
for(String bindingKey : argv){
channel.queueBind(queueName, EXCHANGE_NAME, bindingKey);
}
System.out.println(" [*] Waiting for messages. To exit press CTRL+C");
QueueingConsumer consumer = new QueueingConsumer(channel);
channel.basicConsume(queueName, true, consumer);
while (true) {
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String message = new String(delivery.getBody());
String routingKey = delivery.getEnvelope().getRoutingKey();
System.out.println(" [x] Received '" + routingKey + "':'" + message + "'");
}
}
}
运行接下来的例子,在windows环境中,使用%CP%,包含指南一种的类路径。
接收所有日志:
$ java -cp $CP ReceiveLogsTopic "#"
接收所有灵巧的kern日志:
$ java -cp $CP ReceiveLogsTopic "kern.*"
或者你仅仅想接收'critical'日志:
$ java -cp $CP ReceiveLogsTopic "*.critical"
你可以创建多个绑定:
$ java -cp $CP ReceiveLogsTopic "kern.*" "*.critical"
发出一个路由关键字为"kern.critical"的日志,输入:
$ java -cp $CP EmitLogTopic "kern.critical" "A critical kernel error"
跟这些程序玩的开心。注意代码没有对特定的路由和绑定关键字做臆断,你可以操作多于两个的路由关键字参数。
一些难题:
>““绑定会捕获路由关键字是空的消息吗?
>“#.“会捕获消息中关键字带”..“的吗?它会捕获一个单词的关键字吗?
>“a.*.#和"a.#“之间有什么不同?
接下来,让我们在指南的第六部分,弄清当一个远端程序被调用,如何做一个一个往返的消息。
转载RabbitMQ入门(5)--主题的更多相关文章
- RabbitMQ入门:主题路由器(Topic Exchange)
上一篇博文中,我们使用direct exchange 代替了fanout exchange,这次我们来看下topic exchange. 一.Topic Exchange介绍 topic exchan ...
- RabbitMQ入门(5)——主题(Topic)
前面我们介绍了通过使用direct exchage,改善了fanout exchange只能进行虚拟广播的方式.尽管如此,直接交换也有自身的局限,它不能基于多个条件路由. 在我们的日志系统中,也许我们 ...
- 转载RabbitMQ入门(6)--远程调用
远程过程调用(RPC) (使用Java客户端) 在指南的第二部分,我们学习了如何使用工作队列将耗时的任务分布到多个工作者中. 但是假如我们需要调用远端计算机的函数,等待结果呢?好吧,这又是另一个故事了 ...
- 转载RabbitMQ入门(3)--发布和订阅
发布和订阅 (使用java 客户端) 在先前的指南中,我们创建了一个工作队列.这工作队列后面的假想是每一个任务都被准确的传递给工作者.在这部分我们将会做一些完全不同的事情–我们将一个消息传递给多个消费 ...
- 转载RabbitMQ入门(2)--工作队列
工作队列 (使用Java客户端) 在这第一指南部分,我们写了通过同一命名的队列发送和接受消息.在这一部分,我们将会创建一个工作队列,在多个工作者之间使用分布式时间任务. 工作队列(亦称:任务队列)背后 ...
- 转载RabbitMQ入门(1)--介绍
目录[-] "Hello World" (使用java客户端) 发送 接收 把所有放在一起 前面声明本文都是RabbitMQ的官方指南翻译过来的,由于本人水平有限难免有翻译不当的地 ...
- 转载RabbitMQ入门(4)--路由
路由 (使用Java客户端) 在先前的指南中,我们建立了一个简单的日志系统.我们可以将我们的日志信息广播到多个接收者. 在这部分的指南中,我们将要往其中添加一个功能-让仅仅订阅一个消息的子集成为可能. ...
- RabbitMQ入门:总结
随着上一篇博文的发布,RabbitMQ的基础内容我也学习完了,RabbitMQ入门系列的博客跟着收官了,以后有机会的话再写一些在实战中的应用分享,多谢大家一直以来的支持和认可. RabbitMQ入门系 ...
- RabbitMQ入门教程(七):主题交换机Topics
原文:RabbitMQ入门教程(七):主题交换机Topics 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog. ...
随机推荐
- 并行编译加快 VS C++ 项目的编译速度
最近编译的项目都比较大,话说自己的电脑配置还行,但编译所花的时间还是很长,遇到需要重新编译整个项目的时候真的有回宿舍睡一觉的冲动.昨天一不小心被我发现了一款软件Xoreax IncrediBuild ...
- 关于navicat连接oracle 报 ORA-12737 set CHS16GBK错误的解决方案
[转]关于navicat连接oracle 报 ORA-12737 set CHS16GBK错误的解决方案 昨天下载安装了navicat 9.0 Premium(高级英文版),连接mysql正常,看到他 ...
- C语言关键字register、extern、static
C语言中: 一.register变量 关键字regiter请求编译器尽可能的将变量存在CPU的寄存器中.有以下几点注意的地方. register变量必须是能被CPU寄存器所接受的类型,这通常意味着re ...
- java基础知识回顾之javaIO类--File类应用:获取指定目录下面的指定扩展名的文件,将文件的绝对路径写入到目的文件当中
/** * File文件综合应用 * 需求:获取指定目录下面,指定扩展名的文件,将文件的绝对路径写到文本文件当中. * * 思路:1.需要深度遍历.--递归 * 2.遍历的过程中过滤指定扩展名的文件 ...
- [z]Google SPDY介绍
转自 http://blog.csdn.net/marcky/article/details/7728662 本文主要是参考Google SPDY项目主页的一些文档总结而来,目的整体上介绍SPDY协议 ...
- 【Apache运维基础(1)】Apache的安装与使用
安装 yum -y install httpd httpd-devel # 在Ubuntu里面叫做Apache2,输入localhost能打开就算成功了 额...当然专业的运维还是老老实实的去编译吧; ...
- JAVA XMLConfiguration解决StringXML及多节点
import org.apache.commons.configuration.ConfigurationException; import org.apache.commons.configurat ...
- C语言中时间调用处理的相关函数介绍
asctime(将时间和日期以字符串格式表示) 相关函数:time,ctime,gmtime,localtime 表头文件:#include<time.h> 定义函数:char * asc ...
- SQL Server数据导入导出的几种方法
在涉及到SQL Server编程或是管理时一定会用到数据的导入与导出, 导入导出的方法有多种,结合我在做项目时的经历做一下汇总: 1. SQL Server导入导出向导,这种方式是最方便的. 导入向导 ...
- VB 语言学习笔记.
暂时用到,学习学习. 变量声明 Dim 变量名 as 数据类型类型 Set 实例 = new 类名 自定义数据类型 Type 数据类型标识符 域名 As 数据类型; 域名 As 数据类型; 域名 As ...