Rabbit架构
Rabbit架构如下图所示:
图中包含几个概念:
- 生产者(Producer) : 用来生产与发送消息的角色
- 消费者(Consumer) : 接收并处理消息的角色。
- 代理(Broker) : 中间件服务器,负责接收生产者的消息,根据路由规则将其存储或转发给一个或多个消费者。
- 队列(Queue) : 消息的存储位置,是消息被消费前的临时存放点。
- 交换机(Exchange) : 负责将消息路由到一个或多个队列的组件。
- 虚拟主机(VirtualHost): 虚拟主机,具备隔离效果的一个空间
RabbitMQ的五种模式
1.简单模式【Hello World!】
简单模式下一个消费者对应一个生产者
- publisher直接发送消息到队列
- 消费者监听并处理队列中的消息
使用场景:实际工作中基本用不到
2.工作队列模式【Work Queues】
Work Queues:工作队列模式下一个生产者对应多个消费者。也叫公平分配队列或能者多劳消息队列
- 公平分配:消息平均分配给每个消费者,即使消费者处理完消息也不能获取更多消息
- 能者多劳:消费者之间处于竞争关系,消费者处理完消息就能接收下一条
场景:12306的短信服务。
开启能者多劳所需的配置:
spring:
rabbitmq:
listener:
simple:
prefetch: 1 # 每次只能获取一条消息,处理完成才能获取下一个消息
3.发布订阅模式【Publish/Subscribe】
Publish/Subscribe:一条消息能被多个消费者订阅。发布订阅模式加入了 Exchange(交换机) 这个角色,一旦加入了交换机这个角色,生产者的消息就不再发给队列了,而是发给交换机,再由交换机根据规则路由到队列里面。
- 交换机类型为 fanout:表示为扇出,其实就是无条件群发,此时每个消费者都能接收到消息。
场景:适用于数据大规模分发的情况。中国气象局提供气象信息,腾讯,网易拿到相同的气象信息。
4.路由模式【Routing】
Routing:是发布订阅模式的变种。交换机根据routingKey有条件将数据筛选后发给消费者队列。
- 交换机类型为Direct:订阅,基于RoutingKey(路由key)发送给订阅了消息的队列
- routingKey :路由Key 是一个字符串,用于在消息发布时指定消息的路由信息。
在Direct模型下:
- 队列与交换机的绑定,不能是任意绑定了,而是要指定一个
RoutingKey
(路由key) - 消息的发送方在 向 Exchange发送消息时,也必须指定消息的
RoutingKey
。 - Exchange不再把消息交给每一个绑定的队列,而是根据消息的
Routing Key
进行判断,只有队列的Routingkey
与消息的Routing key
完全一致,才会接收到消息 场景:日志。消费者是监控系统,error的错误日志就会放到消费者队列中。
5.Topic模式【Topics】
Topics:Topic类型的Exchange与Direct相比,都是可以根据RoutingKey把消息路由到不同的队列。 只不过Topic类型Exchange可以让队列在绑定BindingKey 的时候使用通配符
-
交换机类型为Topic:通配符订阅,与Direct类似,只不过RoutingKey可以使用通配符
-
通配符规则
#
:匹配一个或多个词*
:匹配不多不少恰好1个词
-
举例:
item.#
:能够匹配item.spu.insert
或者item.spu
item.*
:只能匹配item.spu
四种交换机
交换机的类型有四种:
- Direct:订阅,基于RoutingKey(路由key)发送给订阅了消息的队列
- Fanout:广播,将消息交给所有绑定到交换机的队列。我们最早在控制台使用的正是Fanout交换机
- Topic:通配符订阅,与Direct类似,只不过RoutingKey可以使用通配符
- Headers:头匹配,基于MQ的消息头匹配,用的较少。
1. 直接交换机(Direct Exchange)
-
定义:直接交换机会将消息路由到与消息的
routingKey
完全匹配的队列。 -
工作原理:
- 生产者发送消息时指定一个
routingKey
。 - 队列通过带有特定
bindingKey
的绑定连接到直接交换机。 - 只有当消息的
routingKey
与队列的bindingKey
完全一致时,该消息才会被投递到对应的队列中。
- 生产者发送消息时指定一个
示例
假设有一个直接交换机 direct_exchange
和两个队列 queue1
和 queue2
,其中:
queue1
绑定到direct_exchange
交换机,并设置bindingKey
为info
。queue2
绑定到同一个交换机,但其bindingKey
为error
。
如果生产者向 direct_exchange
交换机发送一条消息,并且设置了 routingKey
为 info
,那么这条消息只会被发送到 queue1
。同样地,如果消息的 routingKey
是 error
,则它会被发送到 queue2
。
2. 扇出交换机(Fanout Exchange)
-
定义:扇出交换机会将消息广播到所有绑定到它的队列,忽略
routingKey
。 -
工作原理:
- 扇出交换机不关心
routingKey
,它会将消息发送到所有绑定到它的队列。 - 适用于需要将消息广播给多个消费者的场景。
- 扇出交换机不关心
示例
假设有一个扇出交换机 fanout_exchange
和两个队列 queue1
和 queue2
,它们都绑定到 fanout_exchange
交换机。
如果生产者向 fanout_exchange
交换机发送一条消息,无论 routingKey
是什么,这条消息都会被广播到 queue1
和 queue2
。
3. 主题交换机(Topic Exchange)
-
定义:主题交换机会根据
routingKey
和通配符进行模糊匹配来路由消息。 -
工作原理:
-
routingKey
通常由点号(.
)分隔的单词组成。 -
队列可以使用两种通配符来匹配
routingKey
:*
:匹配一个词。#
:匹配零个或多个词。
-
示例
假设有一个主题交换机 topic_exchange
和三个队列 queue1
、queue2
和 queue3
,其中:
queue1
绑定到topic_exchange
交换机,并设置bindingKey
为*.orange.*
。queue2
绑定到同一个交换机,但其bindingKey
为lazy.#
。queue3
绑定到同一个交换机,但其bindingKey
为#.rabbit
。
如果生产者向 topic_exchange
交换机发送一条消息,并且设置了 routingKey
为 lazy.orange.rabbit
,那么这条消息将会被路由到 queue1
和 queue2
。如果 routingKey
是 quick.orange.fox
,那么消息会被路由到 queue1
。如果 routingKey
是 lazy.brown.fox
,那么消息会被路由到 queue2
。
4. 头部交换机(Headers Exchange)
-
定义:头部交换机会根据消息头中的属性来进行路由,而不是
routingKey
。 -
工作原理:
- 头部交换机忽略
routingKey
,而是根据消息头中的属性进行匹配。 - 队列可以绑定到头部交换机并指定一组键值对,只有当消息头中的属性完全匹配这些键值对时,消息才会被路由到相应的队列。
- 头部交换机忽略
示例
假设有一个头部交换机 headers_exchange
和两个队列 queue1
和 queue2
,其中:
queue1
绑定到headers_exchange
交换机,并设置绑定参数为x-match: all, header1: value1, header2: value2
。queue2
绑定到同一个交换机,但其绑定参数为x-match: any, header1: value1, header3: value3
。
如果生产者向 headers_exchange
交换机发送一条消息,并且设置了消息头为 header1: value1, header2: value2
,那么这条消息会被路由到 queue1
。如果消息头为 header1: value1, header3: value3
,那么消息会被路由到 queue2
。