转载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. ...
随机推荐
- catci监控
snmp安装:yum install net-snmp* 配置/etc/snmp/snmpd.conf:com2sec notConfigUser 192.168.79.129 publicac ...
- POJ 2299 Ultra-QuickSort (排序+数据离散化+求顺序数)
题意:给出一个序列,求至少需要用到多少次操作,才能将序列从小到大排序. 思路: 数据量很大,n<500000,所以用冒泡模拟是超时的. 接下来就想到了求顺序数,总共需要交换的次数为每个数后面有多 ...
- LOGSTASH再入门第一发
慢慢弄起来... 前年搞过,现在生疏了,再慢慢拾起来吧. 一些URL: https://www.elastic.co/downloads/logstash https://www.elastic.co ...
- poj 3270 Cow Sorting
思路:仔细读题,看到FARMER是两两交换牛的顺序进行排序的话,应该就往置换上靠拢,而这个题果然是置换的应用(有的解题报告上说是置换群,其实这只是单个置换,不用让它构成群).我们来将这些无序的牛抽象成 ...
- intellij idea 12、13 win8 下 中文输入覆盖的问题(搜狗输入法或者其他输入法)
最近升级到idea12,发现中文输入存在问题,输入中文的时候会出现空格,并且覆盖后面的字符,这个问题让我很郁闷. 假设idea的安装位置为:D:\Program Files\JetBrains\Int ...
- Lambda Action Func练习
namespace lambda { delegate void TestDelegate(string s); class Program { static void Main(string[] a ...
- Project Euler 90:Cube digit pairs 立方体数字对
Cube digit pairs Each of the six faces on a cube has a different digit (0 to 9) written on it; the s ...
- eclipse中clean操作中如何将validating除去
eclipse中去掉js validating方法:1. 删除.project文件中的 <buildSpec></buildSpec>中的:<buildCommand&g ...
- Java学习笔记之:Java流程控制
一.介绍 Java流程控制包括顺序控制.条件控制和循环控制. 顺序控制,就是从头到尾依次执行每条语句操作.条件控制,基于条件选择执行语句,比方说,如果条件成立,则执行操作A,或者如果条件成立,则执行操 ...
- MVVM 代码记录
一.XML <Page x:Class="MVVM.MainPage" xmlns="http://schemas.microsoft.com/winfx/20 ...