主题(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.#“之间有什么不同?

EmitLogTopic.javaReceiveLogsTopic.java的源代码。

接下来,让我们在指南的第六部分,弄清当一个远端程序被调用,如何做一个一个往返的消息。

转载RabbitMQ入门(5)--主题的更多相关文章

  1. RabbitMQ入门:主题路由器(Topic Exchange)

    上一篇博文中,我们使用direct exchange 代替了fanout exchange,这次我们来看下topic exchange. 一.Topic Exchange介绍 topic exchan ...

  2. RabbitMQ入门(5)——主题(Topic)

    前面我们介绍了通过使用direct exchage,改善了fanout exchange只能进行虚拟广播的方式.尽管如此,直接交换也有自身的局限,它不能基于多个条件路由. 在我们的日志系统中,也许我们 ...

  3. 转载RabbitMQ入门(6)--远程调用

    远程过程调用(RPC) (使用Java客户端) 在指南的第二部分,我们学习了如何使用工作队列将耗时的任务分布到多个工作者中. 但是假如我们需要调用远端计算机的函数,等待结果呢?好吧,这又是另一个故事了 ...

  4. 转载RabbitMQ入门(3)--发布和订阅

    发布和订阅 (使用java 客户端) 在先前的指南中,我们创建了一个工作队列.这工作队列后面的假想是每一个任务都被准确的传递给工作者.在这部分我们将会做一些完全不同的事情–我们将一个消息传递给多个消费 ...

  5. 转载RabbitMQ入门(2)--工作队列

    工作队列 (使用Java客户端) 在这第一指南部分,我们写了通过同一命名的队列发送和接受消息.在这一部分,我们将会创建一个工作队列,在多个工作者之间使用分布式时间任务. 工作队列(亦称:任务队列)背后 ...

  6. 转载RabbitMQ入门(1)--介绍

    目录[-] "Hello World" (使用java客户端) 发送 接收 把所有放在一起 前面声明本文都是RabbitMQ的官方指南翻译过来的,由于本人水平有限难免有翻译不当的地 ...

  7. 转载RabbitMQ入门(4)--路由

    路由 (使用Java客户端) 在先前的指南中,我们建立了一个简单的日志系统.我们可以将我们的日志信息广播到多个接收者. 在这部分的指南中,我们将要往其中添加一个功能-让仅仅订阅一个消息的子集成为可能. ...

  8. RabbitMQ入门:总结

    随着上一篇博文的发布,RabbitMQ的基础内容我也学习完了,RabbitMQ入门系列的博客跟着收官了,以后有机会的话再写一些在实战中的应用分享,多谢大家一直以来的支持和认可. RabbitMQ入门系 ...

  9. RabbitMQ入门教程(七):主题交换机Topics

    原文:RabbitMQ入门教程(七):主题交换机Topics 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog. ...

随机推荐

  1. Deep Learning and Shallow Learning

    Deep Learning and Shallow Learning 由于 Deep Learning 现在如火如荼的势头,在各种领域逐渐占据 state-of-the-art 的地位,上个学期在一门 ...

  2. 【Asp.Net MVC】Avoid Mass Assignment in ASP.NET MVC

    Mass Assignment Vulnerability in ASP.NET MVC: http://freshbrewedcode.com/joshbush/2012/03/05/mass-as ...

  3. 将DJANGO管理界面的filter_horizontal移到前面来复用

    参考URL: http://www.hoboes.com/Mimsy/hacks/replicating-djangos-admin/reusing-djangos-filter_horizontal ...

  4. Oracle 体系结构2 - 实例和数据库

    Oracle最最基本的概念: 实例和数据库 实例就是oracle进程和一块共享内存, 数据库就是静态的文件,如datafile, log file, redo logfile, control fil ...

  5. Linux Shell 数字计算与比较

    直接上脚本, 使用$(())以及$[]进行数字计算 数值比较:n1 -eq n2检查n1是否等于n2         n1 -le n2检查n1是否小于等于n2n1 -ge n2检查n1是否大于等于n ...

  6. 【mysql的设计与优化专题(6)】mysql索引攻略

    所谓索引就是为特定的mysql字段进行一些特定的算法排序,比如二叉树的算法和哈希算法,哈希算法是通过建立特征值,然后根据特征值来快速查找,而用的最多,并且是mysql默认的就是二叉树算法 BTREE, ...

  7. Linux 2.4.x内核软中断机制

    http://www.ibm.com/developerworks/cn/linux/kernel/interrupt/ 软中断概况 软中断是利用硬件中断的概念,用软件方式进行模拟,实现宏观上的异步执 ...

  8. iOS开发--即时通讯

    什么是环信? 1.环信是一个第三平台,提供即时通信(IM–Instant Messaging )的服务 2.环信是在XMPP的基础上进行二次开发 3.环信在网络上传输的数据也是XML 4.使用环信,不 ...

  9. 257. Binary Tree Paths

    题目: Given a binary tree, return all root-to-leaf paths. For example, given the following binary tree ...

  10. C++:类型转换

    5.3 类型转换 5.3.1 系统预定义类型间的转换 1. 隐式转换: 例如: int x=5,y;             y=3.5+x; //系统会自动先将int型的5转换为double型的5. ...