Exchange概念
Exchange:交互机,根据路由键转发消息到绑定的队列。

自己说说Exchange在RabbitMQ消息中间件中的作用:
服务器发送消息不会直接发送到队列中(Queue),而是直接发送给交换机(Exchange),然后根据确定的规则,RabbitMQ将会决定消息该投递到哪个队列。这些规则称为路由键(routing key),队列通过路由键绑定到交换机上。消息发送到服务器端(broker),消息也有自己的路由键(也可以是空),RabbitMQ也会将消息和消息指定发送的交换机的绑定(binding,就是队列和交互机的根据路由键映射的关系)的路由键进行匹配。如果匹配的话,就会将消息投递到相应的队列。
Exchange的类型主要有四种,分别是
Direct Exchange:将消息中的
Routing key与该Exchange关联的所有Binding中的Routing key进行比较,如果相等,则发送到该Binding对应的Queue中。Topic Exchange:将消息中的
Routing key与该Exchange关联的所有Binding中的Routing key进行对比,如果匹配上了,则发送到该Binding对应的Queue中。Fanout Exchange:直接将消息转发到所有
binding的对应queue中,这种exchange在路由转发的时候,忽略Routing key。Headers Exchange:将消息中的
headers与该Exchange相关联的所有Binging中的参数进行匹配,如果匹配上了,则发送到该Binding对应的Queue中。
查看exchanges属性,在管控台上查看http://192.168.1.131:15672/#/exchanges


相关属性的说明,如果有多个Virtual host,则还会有Virtual host属性。一般默认的Virtual host是"/",我们知道Virtual host可以做最小粒度的权限控制。

- Virtual host:属于哪个Virtual host。
- Name:名字,同一个Virtual host里面的Name不能重复。
- Durability: 是否持久化,Durable:持久化。Transient:不持久化。
- Auto delete:当最后一个绑定(队列或者exchange)被unbind之后,该exchange自动被删除。
- Internal: 是否是内部专用exchange,是的话,就意味着我们不能往该exchange里面发消息。
- Arguments: 参数,是AMQP协议留给AMQP实现做扩展使用的。
alternate_exchange配置的时候,exchange根据路由路由不到对应的队列的时候,这时候消息被路由到指定的alternate_exchange的value值配置的exchange上。(下面的博客会有说明这参数的具体使用)


unbing之后该exchange删除。
命令行查看exchange信息
使用命令查看exchanges列表,默认的Virtual host
[root@mqserver ~]# rabbitmqctl list_exchanges
Listing exchanges
amq.direct direct
direct
amq.match headers
amq.rabbitmq.log topic
amq.topic topic
amq.headers headers
amq.rabbitmq.trace topic
amq.fanout fanout
指定某个Virtual host的exchanges列表,我指定的事默认的Virtual host(/)
[root@mqserver ~]# rabbitmqctl list_exchanges -p /
Listing exchanges
amq.direct direct
direct
amq.match headers
amq.rabbitmq.log topic
amq.topic topic
amq.headers headers
amq.rabbitmq.trace topic
amq.fanout fanout
使用restful api查看exchanges列表,api的文档地址,(http://192.168.1.131:15672/api/)
对应着下面的链接,当前管控台的url/api

具体的地址,输入对应的用户名和密码,看到对应用户的exchanges列表
http://192.168.1.131:15672/api/exchanges
Direct Exchange
将消息中的Routing key与该Exchange关联的所有Binding中的Routing key进行比较,如果相等,则发送到该Binding对应的Queue中。
- 一个
Exchange可以Binding一个或多个Queue。 - 绑定可以指定
Routing key,Binding的多个Queue可以使用相同的Routing key,也可以使用不同的Routing key。

创建三个Exchange,名称分别是login,logout,register三个exchange。
创建几个Queue,名称分别是PC,WAP,APP,OA。
指定它们的Binding关系,
测试:

查看队列中的消息

其他的可自行测试
特别的Exchange
默认的Exchange(名字为空,AMQP default)
- 默认的
Exchange不能进行Binding操作 - 任何发送到该
Exchange的消息都会被转发到Routing key指定的Queue中 - 如果
vhost中不存在Routing key中指定的队列名,则该消息会被抛弃。


Topic Exchange
将消息中的Routing key与该Exchange关联的所有Binding中的Routing key进行对比,如果匹配上了,则发送到该Binding对应的Queue中。
匹配规则
* 匹配一个单词
# 匹配0个或多个字符
*,# 只能写在.号左右,且不能挨着字符
单词和单词之间需要用.隔开。
列子
- Routing key是user.log.#,因为#是匹配0个或多个字符,所以下面的可以匹配:
user.log
user.log.info
user.log.a
user.log.info.login
- Routing key是user.log.,因为 匹配一个单词,所以
user.log.info 可以匹配
user.log 不能匹配
user.log.info.login 不能匹配,二个单词
- Routing key是#.log.#
可以匹配:
log
user.log
log.info
user.log.info
user.log.info.a
- Routing key是.log.
log 不匹配
user.log 不匹配
log.info 不匹配
user.log.info 匹配,前后各一个单词
user.log.info.a 不匹配
a.user.log.info 不匹配
- Routing key是*.action.#
action 不符合
action.log 不符合
user.action.log 符合
user.action.log.info 符合
user.action 符合
user.log.action 不符合
- Routing key是#.action.*
action 不符合
user.action 不符合
user.action.action 符合
user.action.login 符合
user.action.login.count 不符合
- Routing key是* 表示匹配一个单词
- Routing key是#,或者#.# 表示匹配所有
如果指定了Exchange是Topic类型的,但是相应的Binding中的Routing key *,#都没有,则相等才转发,类似于Direct Exchange
如果Binding中的Routing key为#或者#.#,则全部转发,类似Fanout Exchange(下面会讲到)
测试:
建立一个名称为log的topic类型的Exchange
新建三个队列q1,q2,q3分别绑定 * ,#,#.#

自己定义一脚本,便于测试的时候清除所有队列的消息:
cd /u01
vim purge.sh
curl -X DELETE -u zhihao.miao:123456 http://192.168.1.131:15672/api/queues/%2F/q1/contents
curl -X DELETE -u zhihao.miao:123456 http://192.168.1.131:15672/api/queues/%2F/q2/contents
curl -X DELETE -u zhihao.miao:123456 http://192.168.1.131:15672/api/queues/%2F/q3/contents
curl -X DELETE -u zhihao.miao:123456 http://192.168.1.131:15672/api/queues/%2F/action_queue/contents
curl -X DELETE -u zhihao.miao:123456 http://192.168.1.131:15672/api/queues/%2F/log2_queue/contents
curl -X DELETE -u zhihao.miao:123456 http://192.168.1.131:15672/api/queues/%2F/log_queue/contents
curl -X DELETE -u zhihao.miao:123456 http://192.168.1.131:15672/api/queues/%2F/sys_log_info_queue/contents
curl -X DELETE -u zhihao.miao:123456 http://192.168.1.131:15672/api/queues/%2F/sys_log_queue/contents
curl -X DELETE -u zhihao.miao:123456 http://192.168.1.131:15672/api/queues/%2F/user2_queue/contents
curl -X DELETE -u zhihao.miao:123456 http://192.168.1.131:15672/api/queues/%2F/user_action_queue/contents
curl -X DELETE -u zhihao.miao:123456 http://192.168.1.131:15672/api/queues/%2F/user_log_debug_queue/contents
curl -X DELETE -u zhihao.miao:123456 http://192.168.1.131:15672/api/queues/%2F/user_log_info_queue/contents
curl -X DELETE -u zhihao.miao:123456 http://192.168.1.131:15672/api/queues/%2F/user_log_queue/contents
curl -X DELETE -u zhihao.miao:123456 http://192.168.1.131:15672/api/queues/%2F/user_queue/contents
给脚本授权
chmod 777 purge.sh
执行脚本
sh purge.sh
测试发送Routing key为这些的消息。
user
user.log
user.log.info
user.log.debug
sys
sys.log.debug
特殊情况,定义一队列q4,exchange指定binding为reg,没有*或#,那么当发送的消息route key为reg的时候,能够发送到q4上,此时类似于Direct Exchange。
总结
topic Exchange可以实现Direct Exchange,Fanout Exchange的效果。
Fanout Exchange
直接将消息转发到所有binding的对应queue中,这种exchange在路由转发的时候,忽略Routing key。
Fanout Exchange这种exchange效率最高,fanout > direct > topic
定义一个Fanout类型的Exchange,绑定了一些队列,发送的时候全部队列都能收到消息,而与其bind或者发送消息指定的Routing key无关。

使用topic Exchange实现Fanout Exchange。
topic Exchange将所有binding的queue的routing key都指定为#或者#.#,此时消息也是全部转发。
Headers Exchange
将消息中的headers与该Exchange相关联的所有Binging中的参数进行匹配,如果匹配上了,则发送到该Binding对应的Queue中。
匹配规则:
如果Binding中的
x-match = all:表示所有的键值对都匹配才能转发到消息。
x-match = any: 表示只要有键值对匹配就能转发消息。
注意:
-
Binging的时候,至少需要指定两个参数,其中的一个是x-match = all或x-match = any。 -
Binging的时候,不需要指定Routing key - 发送消息的时候,不需要指定
Routing key - 转发消息的时候,忽略
Routing key - 如果是
x-match = all则发送的headers不能比bingding的参数少,否则匹配不上。
列子:


此时header.debug符合条件,收到消息。

此时还是header.debug符合条件,收到消息。

此时header.debug和header.error都收到消息。

此时header.debug和header.error都收到消息。
