1 fanout exchange
发送到该交换器的所有消息,会被路由到其绑定的所有队列。不处理路由键。你只需要简单的将队列绑定到交换机上。一个发送到交换机的消息都会被转发到与该交换机绑定的所有队列上。很像子网广播,每台子网内的主机都获得了一份复制的消息。Fanout交换机转发消息是最快的。
如图所示,所有发送到 fanout exchange 的消息都会路由到 QUEUE-1 和 QUEUE-2
2 direct exchange
发送到该交换器的消息,会通过路由键完全匹配,匹配成功就会路由到指定队列
处理路由键。需要将一个队列绑定到交换机上,要求该消息与一个特定的路由键完全匹配。这是一个完整的匹配。如果一个队列绑定到该交换机上要求路由键 “abc”,则只有被标记为“abc”的消息才被转发,不会转发abc.def,也不会转发dog.ghi,只会转发abc。
如图所示,发送到 direct exchange 的消息,会通过消息的 routing key 路由:
-
如果
routing key
值为queue.direct.key1
,会路由到QUEUE-1
-
如果
routing key
值为queue.direct.key2
,会路由到QUEUE-2
-
如果
routing key
值为其他,不会路由到任何队列
3 topic exchange
发送到该交换器的消息,会通过路由键模糊匹配,匹配成功就会路由到指定队列
将路由键和某模式进行匹配。此时队列需要绑定要一个模式上。符号“#”匹配一个或多个词,符号“”匹配不多不少一个词。因此“abc.#”能够匹配到“abc.def.ghi”,但是“abc.” 只会匹配到“abc.def”。
路由键通过 . 来划分为多个单词, * 匹配一个单词,# 匹配零个或多个单词
如图所示,发送到 topic exchange 的消息,会通过消息的 routing key 模糊匹配再路由:
-
如果
routing key
值为queue.topic.key1
,会路由到QUEUE-1
和QUEUE-2
-
如果
routing key
值为test.topic.key2
,会路由到QUEUE-1
-
如果
routing key
值为queue
,会路由到QUEUE-2
-
如果
routing key
值为queue.hello
,会路由到QUEUE-2
-
如果
routing key
值为test.test.test
,不会路由到任何队列
4 header exchange
发送到该交换器的消息,会通过消息的 header 信息匹配,匹配成功就会路由到指定队列。
不处理路由键。而是根据发送的消息内容中的headers属性进行匹配。在绑定Queue与Exchange时指定一组键值对;当消息发送到RabbitMQ时会取到该消息的headers与Exchange绑定时指定的键值对进行匹配;如果完全匹配则消息会路由到该队列,否则不会路由到该队列。headers属性是一个键值对,可以是Hashtable,键值对的值可以是任何类型。而fanout,direct,topic 的路由键都需要要字符串形式的。
匹配规则x-match有下列两种类型:
x-match = all :表示所有的键值对都匹配才能接受到消息
x-match = any :表示只要有键值对匹配就能接受到消息
消息的 header 信息是 key-value 的形式,每条消息可以包含多条 header 信息,路由规则是通过 header 信息的 key 来匹配的,Spring Boot 封装的匹配规则有三种:
-
where(key).exists() :匹配单个
key
-
whereAll(keys).exist() :同时匹配多个
key
-
whereAny(keys).exist() :匹配多个
key
中的一个或多个
如图所示,发送到 headers exchange 的消息,会通过消息的 header 匹配:
@Bean
Binding bindingHeadersQueue1(Queue headersQueue1, HeadersExchange headersExchange) {
return BindingBuilder.bind(headersQueue1).to(headersExchange).where("one").exists();
}
@Bean
Binding bindingHeadersQueue2(Queue headersQueue1, HeadersExchange headersExchange) {
return BindingBuilder.bind(headersQueue1).to(headersExchange).whereAll("all1", "all2").exist();
}
@Bean
Binding bindingHeadersQueue3(Queue headersQueue3, HeadersExchange headersExchange) {
return BindingBuilder.bind(headersQueue3).to(headersExchange).whereAny("any1", "any2").exist();
}
如果 header 信息存在 one=XXXX,会路由到 QUEUE-1
如果 header 信息存在 all1=XXXX 和 all2=XXXX,会路由到 QUEUE-2
如果 header 信息存在 any1=XXXX 或 any2=XXXX,会路由到 QUEUE-3
提示:header 不能以 x- 开头
参考官方文档:https://www.rabbitmq.com/tutorials/amqp-concepts.html#exchange-headers
示例代码https://github.com/ChinaSilence/spring-boot-rabbitmq-demos
参考资料https://www.rabbitmq.com/tutorials/amqp-concepts.html