25

消息队列Rabbitmq的交换器类型

 3 years ago
source link: https://segmentfault.com/a/1190000022588933
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

一、交换器类型

在rabbitmq中,生产者的消息都是通过 交换器 来接收,然后再从 交换器 分发到不同的队列中去,在分发的过程中 交换器类型 会影响分发的逻辑。

rabitmq中的 交换器 有4种类型,分别为fanout、direct、topic、headers四种,其中前三种较为常见,后面一种用的比较少。

二、fanout

一般情况下交换器分发会先找出绑定的队列,然后再判断 routekey ,来决定是否将消息分发到某一个队列中;但如果交换器的类型为 fanout ,那么交换器就不再判断 routekey 了,而是将消息直接分发到绑定的队列中去,如下测试代码

Channel channel = connection.createChannel();    //在rabbitmq中创建一个信道
channel.exchangeDeclare("exchangeName", "fanout"); //创建一个type为fanout的交换器    
channel.queueDeclare("queueName");    //创建一个队列
channel.queueBind("queueName", "exchangeName", "routingKey");   //将队列和交换器绑定

三、direct

在类型为 direct 的情况下,交换器在分发消息的时候同样会先获取绑定的队列,然后还会再判断 routeing ;当交换器发现类型为 direct 判断routeing的规则是完全匹配模式,只有消息完全等于到routeing的时候,才会将消息分发到指定队列;

一个队列是可以指定多个路由键的,我们假设有两个队列,分别是 队列一队列二 ;在 队列一 中指定了三个路由键,分别是 zhangsanlisi , wangwu ,在 队列二 中指定了一个队列键 lisi ,指定多个路由键的代码如下所示:

Channel channel = connection.createChannel();    //在rabbitmq中创建一个信道
channel.exchangeDeclare("exchangeName", "direct"); //创建一个type为direct的交换器
channel.queueDeclare("queueName");    //创建一个队列
channel.queueBind("queueName", "exchangeName", "zhangsna");   //绑定并设置路由键
channel.queueBind("queueName", "exchangeName", "lisi");   //绑定并设置路由键
channel.queueBind("queueName", "exchangeName", "wangwu");   //绑定并设置路由键

当生产者发送了一条routeting为 zhangsan 的消息到交换器中,交换器在分发的时候只会把消息分发到 队列一 里面去,因为交换器在routeting匹配的时候只匹配到了 队列一 ,因此 队列二 不会收到消息;

当生产者再次发送了一条routeting为 lisi 的消息到交换器中,交换器在分发的时候会把消息分发到 队列一队列二 两个队列里面去,因为交换器在routeting匹配的时候匹配都匹配成功,因此两个队列都收到了消息;

四、topic

在类型为 topic 的情况下,交换器分发消息的时候也需要同时匹配 bindKeyroutingKey ;但与 direct 类型不同的是当交换器发现类型为 topic 时候,判断routeing的规则是模糊匹配模式。

rabitmq自定义了一套匹配规则,在这里我假设生产者发送了一个消息,其中的的routingKey为 wiki.imooc.com ,那么交换器为 topic 类型时候,想要获取到这条消息,可以用 * 号作为通配符,来指定routingKey,分别是 *.*.com*.imooc.**wiki.imooc.* ;同样也可以使用 # 作为通配符来指定路由键,例如 wiki.##.com

在上面的通配符列子中,我们需要掌握这几点:

  • 路由键以 . 为分隔符,每一个分隔符的代表一个单词
  • 通配符 * 匹配一个单词、通配符 # 可以匹配多个单词
  • * 可以在routingKey和bindKey上使用, # 只能用于RoutingKey中

五、headers

类型为 headers 的交换器与前面三种匹配方式完全不一样,它不依赖与bindingKey和routingKey,而是在绑定队列与交换器的时候指定一个键值对;当交换器在分发消息的时候会先解开消息体里的 headers 数据,然后判断里面是否有所设置的键值对,如果发现匹配成功,才将消息分发到队列中;这种交换器类型在性能上相对来说较差,在实际工作中很少会用到。

六、小结

  1. 从消息分发的性能上来比较: fanout > direct > topic > headers
  2. topic的匹配规则只是用于消费者而不是生产者

作者:汤青松

日期:2020-05-09


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK