前言
上一篇已经通过springboot对rabbitmq的简单封装实现了消息的发送和消费,虽然功能简单,但已经大概了解了它的使用方法。接下来陆续介绍RabbitMQ中的几个核心概念:Queue,Exchange,Channel,vhosts。
本文以Springboot封装的对象Queue来介绍Rabbitmq中的Queue概念。
Queue
Queue(队列)是RabbitMQ的内部对象,用于消息的消费,用下图表示。
![](https://images2018.cnblogs.com/blog/871373/201804/871373-20180426225908165-602366799.png)
图1
RabbitMQ中的消息都只能存储在Queue中,生产者(下图中的P)生产消息并最终投递到Queue中,消费者(下图中的C)可以从Queue中获取消息并消费。
![](https://images2018.cnblogs.com/blog/871373/201804/871373-20180426232853796-1214822885.png)
图2
多个消费者可以订阅同一个Queue,这时Queue中的消息会被平均分摊给多个消费者进行处理,而不是每个消费者都收到所有的消息并处理。
![](https://images2018.cnblogs.com/blog/871373/201804/871373-20180426232916649-764351382.png)
图3
参数:
- name:队列名称
- durable:是否持久化,默认为真。此时即使Rabbitmq服务重启后该队列依然存在。
- exclusive: 默认为否。为真时意味着只被一个连接使用,如果这个连接关闭了,那么队列将被丢弃。
- autoDelete:没有消费者时是否删除该队列,默认为否。
- arguments: Map<String,Object>类型,暂时不是很懂这个,但试了下官网上面的限制队列长度的示例居然启动报错了。
交换机(Exchange)
交换机的功能主要是接收消息并且转发到绑定的队列,交换机不存储消息,在启用ack模式后,交换机找不到队列会返回错误。交换机有四种类型:Direct, topic, Headers and Fanout
- Direct:direct 类型的行为是"先匹配, 再投送". 即在绑定时设定一个 routing_key, 消息的routing_key 匹配时, 才会被交换器投送到绑定的队列中去.
- Topic:按规则转发消息(最灵活)
- Headers:设置header attribute参数类型的交换机
- Fanout:转发消息到所有绑定队列
Direct
Direct Exchange是RabbitMQ默认的交换机模式,也是最简单的模式,根据key全文匹配去寻找队列。
![](https://images2018.cnblogs.com/blog/871373/201804/871373-20180427211029875-85358852.png)
图4
第一个 X - Q1 就有一个 binding key,名字为 orange; X - Q2 就有 2 个 binding key,名字为 black 和 green。当消息中的 路由键 和 这个 binding key 对应上的时候,那么就知道了该消息去到哪一个队列中。
Ps:为什么 X 到 Q2 要有 black,green,2个 binding key呢,一个不就行了吗? - 这个主要是因为可能又有 Q3,而Q3只接受 black 的信息,而Q2不仅接受black 的信息,还接受 green 的信息。
X-orange-Q1组成一个Channel。
topic
Topic Exchange 转发消息主要是根据通配符。 在这种交换机下,队列和交换机的绑定会定义一种路由模式,那么,通配符就要在这种路由模式和路由键之间匹配后交换机才能转发消息。
在这种交换机模式下:
- 路由键必须是一串字符,用句号(.) 隔开,比如说 agreements.us,或者 agreements.eu.stockholm 等。
- 路由模式必须包含一个 星号(),主要用于匹配路由键指定位置的一个单词,比如说,一个路由模式是这样子:agreements..b.,那么就只能匹配路由键是这样子的:第一个单词是 agreements,第四个单词是 b。 井号(#)就表示相当于一个或者多个单词,例如一个匹配模式是agreements.eu.berlin.#,那么,以agreements.eu.berlin开头的路由键都是可以的。
具体代码发送的时候还是一样,第一个参数表示交换机,第二个参数表示routing key,第三个参数即消息。如下:
rabbitTemplate.convertAndSend("testTopicExchange","key1.a.c.key2", " this is RabbitMQ!");
小结:topicExchange是支持通配符的directExchange, 可以使用两个通配符:
-
*
表示一个词. -
#
表示零个或多个词.
|-|key.a|key.a.b|key.b|
|-|-|-|
|key.*|T|F|T|
|key.#|T|T|T|
Headers
headers 也是根据规则匹配, 相较于 direct 和 topic 固定地使用 routing_key , headers 则是一个自定义匹配规则的类型.
在队列与交换器绑定时, 会设定一组键值对规则, 消息中也包括一组键值对( headers 属性), 当这些键值对有一对, 或全部匹配时, 消息被投送到对应队列.
Fanout
Fanout Exchange 消息广播的模式,不管路由键或者是路由模式,会把消息发给绑定给它的全部队列,如果配置了routing_key会被忽略。
小结
Exchange |
Bindings |
测试结果及说明 |
|
Queues |
Routing key |
||
test_direct |
queue00 |
Publish message 时需指定 Routing key。不指定则发送到第一个不用 Routing key 绑定的 queue00;指定 Routing key |
|
queue01 |
rk |
||
queue02 |
kk01 |
||
test_fanout |
queue00 |
message 发送到所有绑定的队列中,即使设置 Routing key 也无效,所依没必要设置多余的 Routing key。 |
|
queue03 |
|||
queue04 |
|||
test_topic |
queue00 |
message 发送时发送到通配符符合的队列中。不指定则发送到第一个不用 Routing key 绑定的 queue00;Publish message 指定 Routing key |
|
queue05 |
aa.# |
||
queue06 |
bb.# |
总结
- Queue用于消息的消费,Exchange则定义了消息的投递规则。
- TopicExchange是最常用的Exchange,重点掌握。