RabbitMQ之Topics

来源:互联网 发布:一个女人的史诗 知乎 编辑:程序博客网 时间:2024/05/20 18:45

在前篇文章中我们改进了我们的日志系统,我们利用direct类型的exchange替代了仅能够简单广播的fanout类型的exchange,并且获得了选择接受日志的可能。

虽然利用direct类型的exchange改进了我们的系统,但它仍然有局限性,它无法基于多个条件进行导航。

在我们的日志系统中我们可能想订阅的不仅仅是基于消息严重性的日志信息,也想订阅基于这日志消息的来源(这日志消息是被谁发送的)。你可能从syslog unix tool中了解到路由日志是基于严重性(info/warn/crit…)和设备(auth/cron/kern…)的这种概念。

这将给我一些灵活性,我们可能想听到仅来自于cron的错误信息和来自kern的所有日志信息。

为了在我们的日志实现这个效果我们需要学习一个更复杂的topic类型的exchange。

Topic exchange

消息被发送到topic类型的exchange 不能是任意路由关键字,这个路由关键字必须是一个以小圆点间隔的单词组。这单词可以是任意的,但他们通常描述了关于这个消息的一些特征。在路由关键字中可以有尽可能多的单词,最大长度是255bytes。

binding关键字也必须是相同的形式,topic类型的exchange背后的逻辑与direct类型的exhange是相似的,一个含有特定路由关键字的消息将被传递到binding关键字匹配的全部队列中。

这里有两个关于binding关键字的特殊情况:
*代表一个单词
#代表0个或多个单词

这里写图片描述

在这个例子中,我们打算发送全部都是描述动物的消息。这消息和由三个单词两个小圆点组成的路由关键字将被发送。路由关键字中的第一个单词将描述速度、第二个描述颜色、第三个描述物种:”..”。

我们创建了三个bindings:
Q1队列绑定*.orange.*这个binding关键字
Q2队列绑定*.*.rabbitlazy.#这两个binding关键字

这些binding能够被概括为:
Q1队列对全部橙色动物感兴趣
Q2队列想听到关于兔子和速度慢吞吞的动物的所有事情

一个路由关键字被设置为quick.orange.rabbit的消息将被传递到这两个队列中。路由关键字为lazy.orange.elephant的消息也将进入这两个队列中。在另一方面,路由关键字为quick.orange.fox的消息将仅进入第一个队列,路由关键字为lazy.brown.fox的消息仅进入第二个队列。路由关键字为lazy.pink.rabbit的消息虽然匹配两个binding但这个消息只会被传递到第二个队列一次。路由关键字quick.brown.fox消息没有匹配到任何binding所以它将被丢弃。

如果我们打破上面的这种规则使被发送消息的路由关键字有一个或四个单词,像orangequick.orange.male.rabbit这样,会发生什么呢?结果是这些消息无法匹配到任意的binding以至于它们将被丢失。

另一方面lazy.orange.male.rabbit虽然有四个单词,但它将匹配最后一个binding并将被传递到第二个队列中。如果你不明白为什么会出现这两个不一样的情况,那么请回到上面关于讲解#含义的部分。

Topic exchange

topic类型的exchange是强大的且能够表现的像其它类型的exchange。

当一个队列被绑定时其binding关键字为#,则它将接收全部的消息而不考虑路由关键字,像fanout类型的exchange一样。
当特殊字符*#没有被用于binding关键字时,topic类型的exchange将表现的像direct类型的exchange一样。

我们打算在我们的日志系统中使用topic类型的exchange。我们先假定日志消息的路由关键字由两个单词组成,其格式为:<facility>.<severity>

这代码与前篇文章中的大部分相似。

javac -cp %CP% ReceiveLogsTopic.java EmitLogTopic.java

接收全部的日志:

java -cp $CP ReceiveLogsTopic "#"

接收来自kern设备的全部消息:

java -cp $CP ReceiveLogsTopic "kern.*"

如果你想仅听到关于critical的日志信息:

java -cp $CP ReceiveLogsTopic "*.critical"

你能创建多个binding

java -cp $CP ReceiveLogsTopic "kern.*" "*.critical"

设置被发送日志的路由关键字为”kern.critical” :

java -cp $CP EmitLogTopic "kern.critical" "A critical kernel error"

本篇内容的代码稍后再补充