Contents
  1. 1. Topic exchange
  2. 2. 应用案例
  3. 3. Topic exchange
  4. 4. 汇总

上一节中,使用Dircet Exchange结合routingKey及bindingKey可以实现选择性地接收消息。但是它也有局限性,无法基于多种尺度来路由。

比如说日志系统中我们可能不仅希望根据级别,还希望根据日志发出者的身份来进行路由。比如syslog unix工具,就是根据severity和facility(auth/cron/kern…)来进行路由的。

这各方式更具灵活性,比如我想接收来自cron的Error信息和来自Kern的所有信息。

要实现这样的功能我们需要学习更复杂的Topic exchange。

Topic exchange

发送给topic exchange的信息的routingKey必须是一个word的list,用.号分隔。习惯上用一些能够代表消息特征单词来作为word,比如stock.usd.nyse是一个合法的routingKey。word不限个数,但总长不能超过255 Byte。

bindingKey也必须是这样的形式,而路由逻辑则和Direct方式相似,消息将被发送给所有bindingKey和RoutingKey匹配的队列。但是有两wildcard:

\* 能替换成任何一个(单个)word
# 能替换成任意(0-n)个word

应用案例

以下的例子是,消息都是描述动物的,由三个word组成,第一个描述速度,第二个描述颜色,第三个描述种类。即

1
<speed>.<colour>.<species>

创建Binding x 2:

  • Q1: *.orange.*
  • Q2 *.*.rabbit + lazy.# (两个BindingKey)

关于以上Binding的解释:

  • Q1对所有橙色动物感兴趣
  • Q2对兔子和懒惰动物感兴趣

routingKey = quick.orange.rabbit的消息将同时发送给Q1和Q2,lazy.orange.elephant也是。quick.orange.fox只发给Q1,lazy.pink.rabbit只给Q2,且只发送一次(虽然两个BindingKey都匹配),quick.brown.fox将被丢弃。

如果我们发送不合预期格式的消息呢?比如routingKey = orangequick.orange.male.rabbit?因为不匹配任何BindingKey,所以消息会被丢弃。

也就是说lazy.orange.male.rabbit将匹配Q2的第二个Binding,因为会被Q2收到。

Topic exchange

Topic Exchange功能强大,可配置成像其它几种Exchange一样工作。

BindingKey=#,将成为fanout。

如果不使用#和*这样的符号,那么就成为了direct。

汇总

回到之前日志系统,我们的routing key有两个words: <facility>.<severity>

代码和上一节,除了更换Exchange类型,基本一样。

先看运行效果,bindingkey和消息的routingKey都是在参数中指定的。

可以看到实现了预期的效果。

因为和上一节一样(只更改Exchange类型),所以就不再帖了。

Contents
  1. 1. Topic exchange
  2. 2. 应用案例
  3. 3. Topic exchange
  4. 4. 汇总