本节目标
- 了解 AMQP 模型
- 了解 Exchange
建议大家在学习MQ之前,先了解一下 生产者消费者模型,可以参考我之前的一篇 Java 理解生产者-消费者设计模式
AMQP 简介
RabbitMQ 是实现了 AMQP 协议的消息中间件,所以说下面讲到这些概念不仅限于RabbitMQ,所有实现AMQP 协议的消息中间件都具备这些
AMQP 模型图如下
Publisher(发布者)和 Consumer(消费者)可以理解为是我们的应用程序
Exchange(交换机),我们的Publisher 会将消息先推送到Exchange ,Exchange 类似邮局,他会将消息再路由到 Queue(队列)中,Queue会将消息推送给Consumer
Exchange 和 Queue 之间通过 Binding (绑定)将两者关联到一起,一个Exchange 可以绑定多个Queue,一个Queue 可以绑定多个Exchange
Exchange
刚刚我们说Exchange类似邮局。邮局的话,当然会有很多的邮递方式,所以我们的Exchange有多种类型,每种类型都有自己的策略
AMQP 提供四种Exchange类型
name | 默认预设名 |
---|---|
Direct exchange | (Empty string) and amq.direct |
Fanout exchange | amq.fanout |
Topic exchange | amq.topic |
Headers exchange | amq.match (and amq.headers in RabbitMQ) |
Direct Exchange
Rabbit 文档中给出的定义翻译过来是这样的
Direct Exchange基于RoutingKey 将消息传递到队列
通俗点讲是啥意思呢,直接看代码吧
1 | // 第一个参数为Exchange,第二个参数就是RoutingKey |
我们再来看绑定的时候,也会关联一个RoutingKey1
2// 绑定的时候 也会关联一个RoutingKey
BindingBuilder.bind(queue()).to(userExchange()).with("user_routingKey")
千言万语都在图里
Default Exchange
Default Exchange 其实是AMQP中预先声明的,并且它属于 Direct Exchange,通常来说每个Exchange都会有自己的名,Default Exchange 的名是 ""
.
他有一个特殊的属性,当你手动创建一个队列时,MQ会自动将这个队列绑定到Default Exchange 上,绑定时 RoutingKey 与队列名称相同
说的好像挺绕的,来看一下代码吧1
2
3
4
5// 声明一个 Queue,这个时候我们不主动Binding的话,test_queue 会和Default Exchange 绑定,此时 routingKey = test_queue
Queue queue = new Queue("test_queue");
// 向默认交换机发布消息
rabbitTemplate.convertAndSend("", "test_queue", message);
Fanout Exchange
Fanout Exchange 很简单,适合发布订阅场景。他不使用RoutingKey,他将消息路由到所有与其绑定的队列
Topic Exchange
Topic Exchange 又是基于RoutingKey来路由转发的,但是有些不同,上图
在使用 Topic 的时候,routingKey 可以是 *.orange.*
,lazy.#
这种表达式
*
(星) 代表一个词.#
(hash) 代表0或多个词.
同理,当发布消息时的 routingKey 与其匹配时,会路由到相应的队列
Headers Exchange
基于Header中的属性来匹配路由,由于不是很常用,这里就不说了