Exchange概念
Exchange:交互機(jī),根據(jù)路由鍵轉(zhuǎn)發(fā)消息到綁定的隊(duì)列。

自己說(shuō)說(shuō)Exchange在RabbitMQ消息中間件中的作用:
服務(wù)器發(fā)送消息不會(huì)直接發(fā)送到隊(duì)列中(Queue),而是直接發(fā)送給交換機(jī)(Exchange),然后根據(jù)確定的規(guī)則,RabbitMQ將會(huì)決定消息該投遞到哪個(gè)隊(duì)列。這些規(guī)則稱為路由鍵(routing key),隊(duì)列通過(guò)路由鍵綁定到交換機(jī)上。消息發(fā)送到服務(wù)器端(broker),消息也有自己的路由鍵(也可以是空),RabbitMQ也會(huì)將消息和消息指定發(fā)送的交換機(jī)的綁定(binding,就是隊(duì)列和交互機(jī)的根據(jù)路由鍵映射的關(guān)系)的路由鍵進(jìn)行匹配。如果匹配的話,就會(huì)將消息投遞到相應(yīng)的隊(duì)列。
Exchange的類型主要有四種,分別是
Direct Exchange:將消息中的
Routing key與該Exchange關(guān)聯(lián)的所有Binding中的Routing key進(jìn)行比較,如果相等,則發(fā)送到該Binding對(duì)應(yīng)的Queue中。Topic Exchange:將消息中的
Routing key與該Exchange關(guān)聯(lián)的所有Binding中的Routing key進(jìn)行對(duì)比,如果匹配上了,則發(fā)送到該Binding對(duì)應(yīng)的Queue中。Fanout Exchange:直接將消息轉(zhuǎn)發(fā)到所有
binding的對(duì)應(yīng)queue中,這種exchange在路由轉(zhuǎn)發(fā)的時(shí)候,忽略Routing key。Headers Exchange:將消息中的
headers與該Exchange相關(guān)聯(lián)的所有Binging中的參數(shù)進(jìn)行匹配,如果匹配上了,則發(fā)送到該Binding對(duì)應(yīng)的Queue中。
查看exchanges屬性,在管控臺(tái)上查看http://192.168.1.131:15672/#/exchanges


相關(guān)屬性的說(shuō)明,如果有多個(gè)Virtual host,則還會(huì)有Virtual host屬性。一般默認(rèn)的Virtual host是"/",我們知道Virtual host可以做最小粒度的權(quán)限控制。

- Virtual host:屬于哪個(gè)Virtual host。
- Name:名字,同一個(gè)Virtual host里面的Name不能重復(fù)。
- Durability: 是否持久化,Durable:持久化。Transient:不持久化。
- Auto delete:當(dāng)最后一個(gè)綁定(隊(duì)列或者exchange)被unbind之后,該exchange自動(dòng)被刪除。
- Internal: 是否是內(nèi)部專用exchange,是的話,就意味著我們不能往該exchange里面發(fā)消息。
- Arguments: 參數(shù),是AMQP協(xié)議留給AMQP實(shí)現(xiàn)做擴(kuò)展使用的。
alternate_exchange配置的時(shí)候,exchange根據(jù)路由路由不到對(duì)應(yīng)的隊(duì)列的時(shí)候,這時(shí)候消息被路由到指定的alternate_exchange的value值配置的exchange上。(下面的博客會(huì)有說(shuō)明這參數(shù)的具體使用)


unbing之后該exchange刪除。
命令行查看exchange信息
使用命令查看exchanges列表,默認(rèn)的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
指定某個(gè)Virtual host的exchanges列表,我指定的事默認(rèn)的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/)
對(duì)應(yīng)著下面的鏈接,當(dāng)前管控臺(tái)的url/api

具體的地址,輸入對(duì)應(yīng)的用戶名和密碼,看到對(duì)應(yīng)用戶的exchanges列表
http://192.168.1.131:15672/api/exchanges
Direct Exchange
將消息中的Routing key與該Exchange關(guān)聯(lián)的所有Binding中的Routing key進(jìn)行比較,如果相等,則發(fā)送到該Binding對(duì)應(yīng)的Queue中。
- 一個(gè)
Exchange可以Binding一個(gè)或多個(gè)Queue。 - 綁定可以指定
Routing key,Binding的多個(gè)Queue可以使用相同的Routing key,也可以使用不同的Routing key。

創(chuàng)建三個(gè)Exchange,名稱分別是login,logout,register三個(gè)exchange。
創(chuàng)建幾個(gè)Queue,名稱分別是PC,WAP,APP,OA。
指定它們的Binding關(guān)系,
測(cè)試:

查看隊(duì)列中的消息

其他的可自行測(cè)試
特別的Exchange
默認(rèn)的Exchange(名字為空,AMQP default)
- 默認(rèn)的
Exchange不能進(jìn)行Binding操作 - 任何發(fā)送到該
Exchange的消息都會(huì)被轉(zhuǎn)發(fā)到Routing key指定的Queue中 - 如果
vhost中不存在Routing key中指定的隊(duì)列名,則該消息會(huì)被拋棄。


Topic Exchange
將消息中的Routing key與該Exchange關(guān)聯(lián)的所有Binding中的Routing key進(jìn)行對(duì)比,如果匹配上了,則發(fā)送到該Binding對(duì)應(yīng)的Queue中。
匹配規(guī)則
* 匹配一個(gè)單詞
# 匹配0個(gè)或多個(gè)字符
*,# 只能寫在.號(hào)左右,且不能挨著字符
單詞和單詞之間需要用.隔開(kāi)。
列子
- Routing key是user.log.#,因?yàn)?是匹配0個(gè)或多個(gè)字符,所以下面的可以匹配:
user.log
user.log.info
user.log.a
user.log.info.login
- Routing key是user.log.,因?yàn)?/em> 匹配一個(gè)單詞,所以
user.log.info 可以匹配
user.log 不能匹配
user.log.info.login 不能匹配,二個(gè)單詞
- 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 匹配,前后各一個(gè)單詞
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是* 表示匹配一個(gè)單詞
- Routing key是#,或者#.# 表示匹配所有
如果指定了Exchange是Topic類型的,但是相應(yīng)的Binding中的Routing key *,#都沒(méi)有,則相等才轉(zhuǎn)發(fā),類似于Direct Exchange
如果Binding中的Routing key為#或者#.#,則全部轉(zhuǎn)發(fā),類似Fanout Exchange(下面會(huì)講到)
測(cè)試:
建立一個(gè)名稱為log的topic類型的Exchange
新建三個(gè)隊(duì)列q1,q2,q3分別綁定 * ,#,#.#

自己定義一腳本,便于測(cè)試的時(shí)候清除所有隊(duì)列的消息:
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
給腳本授權(quán)
chmod 777 purge.sh
執(zhí)行腳本
sh purge.sh
測(cè)試發(fā)送Routing key為這些的消息。
user
user.log
user.log.info
user.log.debug
sys
sys.log.debug
特殊情況,定義一隊(duì)列q4,exchange指定binding為reg,沒(méi)有*或#,那么當(dāng)發(fā)送的消息route key為reg的時(shí)候,能夠發(fā)送到q4上,此時(shí)類似于Direct Exchange。
總結(jié)
topic Exchange可以實(shí)現(xiàn)Direct Exchange,Fanout Exchange的效果。
Fanout Exchange
直接將消息轉(zhuǎn)發(fā)到所有binding的對(duì)應(yīng)queue中,這種exchange在路由轉(zhuǎn)發(fā)的時(shí)候,忽略Routing key。
Fanout Exchange這種exchange效率最高,fanout > direct > topic
定義一個(gè)Fanout類型的Exchange,綁定了一些隊(duì)列,發(fā)送的時(shí)候全部隊(duì)列都能收到消息,而與其bind或者發(fā)送消息指定的Routing key無(wú)關(guān)。

使用topic Exchange實(shí)現(xiàn)Fanout Exchange。
topic Exchange將所有binding的queue的routing key都指定為#或者#.#,此時(shí)消息也是全部轉(zhuǎn)發(fā)。
Headers Exchange
將消息中的headers與該Exchange相關(guān)聯(lián)的所有Binging中的參數(shù)進(jìn)行匹配,如果匹配上了,則發(fā)送到該Binding對(duì)應(yīng)的Queue中。
匹配規(guī)則:
如果Binding中的
x-match = all:表示所有的鍵值對(duì)都匹配才能轉(zhuǎn)發(fā)到消息。
x-match = any: 表示只要有鍵值對(duì)匹配就能轉(zhuǎn)發(fā)消息。
注意:
-
Binging的時(shí)候,至少需要指定兩個(gè)參數(shù),其中的一個(gè)是x-match = all或x-match = any。 -
Binging的時(shí)候,不需要指定Routing key - 發(fā)送消息的時(shí)候,不需要指定
Routing key - 轉(zhuǎn)發(fā)消息的時(shí)候,忽略
Routing key - 如果是
x-match = all則發(fā)送的headers不能比bingding的參數(shù)少,否則匹配不上。
列子:


此時(shí)header.debug符合條件,收到消息。

此時(shí)還是header.debug符合條件,收到消息。

此時(shí)header.debug和header.error都收到消息。

此時(shí)header.debug和header.error都收到消息。