RabbitMQ Exchange类型和工作模式介绍
- 一RabbitMQ Exchange类型
- 1.1.Fanout
- 1.2.Direct
- 1.3.Topic
- 1.4.Headers
- 二 RabbitMQ 工作模式介绍
- 2.1.work工作模式(资源的竞争)
- 2.2.publish/subscribe发布订阅(共享资源)
- 2.3.routing路由模式
- 应用--direct交换器
- 2.4.topic 主题模式(路由模式的一种)
一RabbitMQ Exchange类型
RabbitMQ常用的交换器类型有: fanout、 direct、 topic、 headers四种。
1.1.Fanout
会把所有发送到该交换器的消息路由到所有与该交换器绑定的队列中
如图:
1.2.Direct
direct类型的交换器路由规则很简单,它会把消息路由到那些BindingKey和RoutingKey完全匹配的 队列中,如下图:
1.3.Topic
topic类型的交换器在direct匹配规则上进行了扩展,也是将消息路由到BindingKey和RoutingKey 相匹配的队列中,这里的匹配规则稍微不同,它约定:
- BindingKey和RoutingKey一样都是由
.
分隔的字符串; - BindingKey中可以存在两种特殊字符
*
和#
,用于模糊匹配,其中*
用于匹配一个单词,#
用于匹配多个单词(可以是0个)。
1.4.Headers
headers类型的交换器不依赖于路由键的匹配规则来路由信息,而是根据发送的消息内容中的 headers属性进行匹配。在绑定队列和交换器时指定一组键值对,当发送的消息到交换器时, RabbitMQ会获取到该消息的headers,对比其中的键值对是否完全匹配队列和交换器绑定时指定的键值对,如果匹配,消息就会路由到该队列。headers类型的交换器性能很差,不实用。
二 RabbitMQ 工作模式介绍
2.1.work工作模式(资源的竞争)
生产者发消息,启动多个消费者实例来消费消息,每个消费者仅消费部分信息,可达到负载均衡的效果。
1.消息产生者将消息放入队列消费者可以有多个,消费者1,消费者2同时监听同一 个队列,消息被消费。C1 C2共同争抢当前的消息队列内容,谁先拿到谁负责消费消息(隐患:高并发情况下,默认会产生某一个消息被多个消费者共同使用,可以设置一个开关(syncronize) 保证一条消息只能被一个消费者使用)。
2.2.publish/subscribe发布订阅(共享资源)
使用fanout类型交换器,routingKey忽略。每个消费者定义生成一个队列并绑定到同一个 Exchange,每个消费者都可以消费到完整的消息。
1、每个消费者监听自己的队列
2、生产者将消息发给broker,由交换机将消息转发到绑定此交换机的每个队列,每个绑定交换机的队列都将接收到消息。
2.3.routing路由模式
使用 direct类型的Exchange,发N条消费并使用不同的 routingKey,消费者定义队列并将队列、 routingKey、Exchange绑定。此时使用 direct模式Exchagne必须要 routingKey完全匹配的 情况下消息才会转发到对应的队列中被消费。
上一个模式中,可以将消息广播到很多接收者。 现在我们想让接收者只接收部分消息,如,我们通过直接模式的交换器将关键的错误信息记录到 log文件,同时在控制台正常打印所有的日志信息。
应用–direct交换器
分布式系统中有很多应用,这些应用需要运维平台的监控,其中一个重要的信息就是服务器的日志 记录。
我们需要将不同日志级别的日志记录交给不同的应用处理。 如何解决?
使用direct交换器
如果要对不同的消息做不同的处理,此时不能使用 fanout类型的交换器,因为它只会盲目的广播消息。 我们需要使用 direct类型的交换器。 direct交换器的路由算法很简单:只要消息的 routingKey和队列的 bindingKey对应,消息就可以推送给该队列。
上图中的交换器 X是 direct类型的交换器,绑定的两个队列中,一个队列的 bindingKey是 orange,另一个队列的 bindingKey是 black和 green。 如此,则 routingKey是 orange的消息发送给队列Q1, routingKey是 black和 green的消息发 送给Q2队列,其他消息丢弃。
2.4.topic 主题模式(路由模式的一种)
使用 topic类型的交换器,队列绑定到交换器、 bindingKey时使用通配符,交换器将消息路由转 发到具体队列时会根据消息 routingKey模糊匹配,比较灵活。
上个模式中,我们通过 direct类型的交换器做到了根据日志级别的不同,将消息发送给了不同队列的。 这里有一个限制,现在我不仅想根据日志级别划分日志消息,还想根据日志来源划分日志,怎 么做?
比如,我想监听cron服务发送的 error消息,又想监听从kern服务发送的所有消息。 此时可以使用RabbitMQ的主题模式( Topic)。
要想 topic类型的交换器, routingKey就不能随便写了,它必须得是点分单词。单词可以随便写,生产中一般使用消息的特征。如:“stock.usd.nyse”,“nyse.vmw”,“quick.orange.rabbit”等。该点分单词字符串最长255字节。 bindingKey也必须是这种形式。 topic类型的交换器背后原理跟 direct类型的类似:只要队列 的 bindingKey的值与消息的 routingKey匹配,队列就可以收到该消息。有两个不同:
- *(star)匹配一个单词
- #匹配0到多个单词
上图中,我们发送描述动物的消息。消息发送的时候指定的 routingKey包含了三个词,两个点。 第一个单词表示动物的速度,第二个是颜色,第三个是物种:..。
创建三个绑定:
Q1绑定到*.orange.*
Q2绑定到 *.*.rabbit
和 lazy.#
。
-
Q1关注orange颜色动物的消息
-
Q2关注兔子的消息,以及所有懒的动物消息
如果不能匹配,就丢弃消息。
如果发送的消息 routingKey是" lazy.orange.male.rabbit",则会匹配最后一个绑定。
如果在 topic类型的交换器中 bindingKey使用 #,则就是 fanout类型交换器的行为。
如果在 topic类型的交换器中 bindingKey中不使用 *和 #,则就是 direct类型交换器的行为