1 RabbitMQ安裝部署
這里是ErLang環(huán)境的下載地址
http://www.erlang.org/downloads
這是RabbitMQ環(huán)境忆嗜、客戶端脾猛、實(shí)例和說明文檔的地址
http://www.rabbitmq.com/download.html
默認(rèn)安裝的Rabbit MQ 監(jiān)聽端口是:5672
進(jìn)入目錄
CD D:\Program Files\RabbitMQ Server\rabbitmq_server-3.6.10\sbin
安裝完以后erlang需要手動(dòng)設(shè)置ERLANG_HOME 的系統(tǒng)變量。
set ERLANG_HOME=D:\Program Files\erl9.0
激活Rabbit MQ's Management Plugin
rabbitmq-plugins.bat enable rabbitmq_management
創(chuàng)建管理用戶甘苍,所有的賬號(hào)設(shè)置伴榔,都是區(qū)分大小寫的,千萬注意
rabbitmqctl.bat add_user BOEREms BOEREms1703
設(shè)置管理員陕截,設(shè)置管理員前,BOEREms這個(gè)賬號(hào)要先創(chuàng)建驹沿,否則設(shè)置就會(huì)失敗艘策。
rabbitmqctl.bat set_user_tags BOEREms administrator
設(shè)置權(quán)限
rabbitmqctl.bat set_permissions -p / BOEREms ".*" ".*" ".*"
查詢用戶
rabbitmqctl.bat list_users
查詢vhosts
rabbitmqctl.bat list_vhosts
啟動(dòng)RabbitMQ服務(wù):
net stop RabbitMQ && net start RabbitMQ蹈胡, 可以通過工具啟動(dòng)和關(guān)閉RabbitMQ服務(wù)
訪問Rabbit Mq的管理控制臺(tái)渊季,使用剛才創(chuàng)建的賬號(hào)登陸系統(tǒng)即可。
Rabbit MQ 管理后臺(tái)罚渐,可以更好的可視化方式查看RabbitMQ服務(wù)器實(shí)例的狀態(tài)却汉。
http://localhost:15672
Virtual Host:UploadQueue
D:\Program Files\RabbitMQ Server\rabbitmq_server-3.6.10\sbin>rabbitmq-plugins.ba
t enable rabbitmq_management
Plugin configuration unchanged.
Applying plugin configuration to rabbit@WIN-7BVDCM2AUG0... failed.
* Could not contact node rabbit@WIN-7BVDCM2AUG0.
Changes will take effect at broker restart.
* Options: --online - fail if broker cannot be contacted.
--offline - do not try to contact broker.
D:\Program Files\RabbitMQ Server\rabbitmq_server-3.6.10\sbin>rabbitmqctl status
Status of node 'rabbit@WIN-7BVDCM2AUG0'
Error: unable to connect to node 'rabbit@WIN-7BVDCM2AUG0': nodedown
DIAGNOSTICS
===========
attempted to contact: ['rabbit@WIN-7BVDCM2AUG0']
rabbit@WIN-7BVDCM2AUG0:
* connected to epmd (port 4369) on WIN-7BVDCM2AUG0
* epmd reports node 'rabbit' running on port 25672
* TCP connection succeeded but Erlang distribution failed
* Authentication failed (rejected by the remote node), please check the Erlang
cookie
current node details:
- node name: 'rabbitmq-cli-17@WIN-7BVDCM2AUG0'
- home dir: C:\Users\Administrator
- cookie hash: /352utUNRCCPsDbXHre2Dw==
具體操作:將 C:\WINDOWS\.erlang.cookie 同步到RabbitMq 啟動(dòng)用戶 例如win10:C:\Users\%USERNAME%\.erlang.cookie
2 RabbitMQ原理簡介
首先這個(gè)過程走分三個(gè)部分,1荷并、客戶端(生產(chǎn)消息隊(duì)列)合砂,2、RabbitMQ服務(wù)端(負(fù)責(zé)路由規(guī)則的綁定與消息的分發(fā))源织,3翩伪、客戶端(消費(fèi)消息隊(duì)列中的消息);由圖可以看出谈息,一個(gè)消息可以走一次網(wǎng)絡(luò)卻被分發(fā)到不同的消息隊(duì)列中缘屹,然后被多個(gè)的客戶端消費(fèi),那么這個(gè)過程就是RabbitMQ的核心機(jī)制侠仇,RabbitMQ的路由類型與消費(fèi)模式轻姿。
RabbitMQ中間件分為服務(wù)端(RabbitMQ Server)和客戶端(RabbitMQ Client),服務(wù)端可以理解為是一個(gè)消息的代理消費(fèi)者逻炊,客戶端又分為消息生產(chǎn)者(Producer)和消息消費(fèi)者(Consumer)互亮。
- 消息生產(chǎn)者(Producer):主要生產(chǎn)消息并將消息基于TCP協(xié)議,通過建立Connection和Channel余素,將消息傳輸給RabbitMQ Server豹休,對(duì)于Producer而言基本就完成了工作。
- 服務(wù)端(RabbitMQ Server):主要負(fù)責(zé)處理消息路由桨吊、分發(fā)威根、入隊(duì)列窑眯、緩存和出列。主要由三部分組成:Exchange医窿、RoutingKey磅甩、Queue。
- Exchange:用于接收消息生產(chǎn)者發(fā)送的消息姥卢,有三種類型的exchange:direct, fanout,topic卷要,不同類型實(shí)現(xiàn)了不同的路由算法;
A. direct exchange:將與routing key 比配的消息独榴,直接推入相對(duì)應(yīng)的隊(duì)列僧叉,創(chuàng)建隊(duì)列時(shí),默認(rèn)就創(chuàng)建同名的routing key棺榔。
B. fanout exchange:是一種廣播模式瓶堕,忽略routingkey的規(guī)則。
C. topic exchange:應(yīng)用主題症歇,根據(jù)key進(jìn)行模式匹配路由郎笆,例如:若為abc則推入到所有abc相對(duì)應(yīng)的queue;若為abc.#則推入到abc.xx.one ,abc.yy.two對(duì)應(yīng)的queue忘晤。
- RoutingKey:是RabbitMQ實(shí)現(xiàn)路由分發(fā)到各個(gè)隊(duì)列的規(guī)則宛蚓,并結(jié)合Binging提供于Exchange使用將消息推送入隊(duì)列;
- Queue:是消息隊(duì)列设塔,可以根據(jù)需要定義多個(gè)隊(duì)列凄吏,設(shè)置隊(duì)列的屬性,比如:消息移除闰蛔、消息緩存痕钢、回調(diào)機(jī)制等設(shè)置,實(shí)現(xiàn)與Consumer通信序六;
- 消息消費(fèi)者(Consumer):主要負(fù)責(zé)消費(fèi)Queue的消息任连,同樣基于TCP協(xié)議,通過建立Connection和Channel與Queue傳輸消息难咕,一個(gè)消息可以給多個(gè)Consumer消費(fèi)课梳;
- 關(guān)鍵名詞說明:Connection、Channel余佃、Binging等暮刃;
- Connection:是建立客戶端與服務(wù)端的連接。
- Channel:是基于Connection之上建立通信通道爆土,因?yàn)槊看蜟onnection建立TCP協(xié)議通信開銷及性能消耗較大椭懊,所以一次建立Connection后,使用多個(gè)Channel通道通信減少開銷和提高性能。
- Binging:是一個(gè)捆綁定義氧猬,將exchange和queue捆綁背犯,定義routingkey相關(guān)策略。
3 RabbitMQ中的一些名詞闡述與消息從投遞到消費(fèi)的整個(gè)過程
從上圖的標(biāo)題中可以看到一些陌生的英文單詞盅抚,讓我們感覺一無所知漠魏,更無從操作,那么我給大家弄啦一個(gè)圖片大家可以看下妄均,或許對(duì)您理解這些新鮮的單詞有所幫助柱锹。
看過這些名詞,之后丰包,或許你還毫無頭緒禁熏,那么我把消息從生產(chǎn)到消費(fèi)的整個(gè)流程給大家說一下,或許會(huì)更深入一點(diǎn)邑彪,其中Exchange瞧毙,與Queue都是可以設(shè)置相關(guān)屬性,隊(duì)列的持久化寄症,交換器類型制定宙彪。
4 RabbitMQ中Exchange的類型
Direct Exchange是RabbitMQ默認(rèn)的交換機(jī)模式,也是最簡單的模式瘸爽,根據(jù)key全文匹配去尋找隊(duì)列您访。
類型有4種铅忿,direct剪决,fanout,topic檀训,headers柑潦。其中headers不常用,本篇不做介紹峻凫,其他三種類型渗鬼,會(huì)做詳細(xì)介紹。
那么這些類型是什么意思呢荧琼?就是Exchange與隊(duì)列進(jìn)行綁定后譬胎,消息根據(jù)exchang的類型,按照不同的綁定規(guī)則分發(fā)消息到消息隊(duì)列中命锄,可以是一個(gè)消息被分發(fā)給多個(gè)消息隊(duì)列堰乔,也可以是一個(gè)消息分發(fā)到一個(gè)消息隊(duì)列。具體請(qǐng)看下文脐恩。
介紹之初還要說下RoutingKey镐侯,這是個(gè)什么玩意呢?他是exchange與消息隊(duì)列綁定中的一個(gè)標(biāo)識(shí)驶冒。有些路由類型會(huì)按照標(biāo)識(shí)對(duì)應(yīng)消息隊(duì)列苟翻,有些路由類型忽略routingkey韵卤。具體看下文。
- Exchange類型direct
他是根據(jù)交換器名稱與routingkey來找隊(duì)列的崇猫。
第一個(gè) X - Q1 就有一個(gè) binding key沈条,名字為 orange; X - Q2 就有 2 個(gè) binding key诅炉,名字為 black 和 green拍鲤。當(dāng)消息中的 路由鍵 和 這個(gè) binding key 對(duì)應(yīng)上的時(shí)候,那么就知道了該消息去到哪一個(gè)隊(duì)列中汞扎。
Ps:為什么 X 到 Q2 要有 black季稳,green,2個(gè) binding key呢澈魄,一個(gè)不就行了嗎景鼠? - 這個(gè)主要是因?yàn)榭赡苡钟?Q3,而Q3只接受 black 的信息痹扇,而Q2不僅接受black 的信息铛漓,還接受 green 的信息。
Note:消息從client發(fā)出鲫构,傳送給交換器ChangeA浓恶,RoutingKey為routingkey.ZLH,那么不管你發(fā)送給Queue1,還是Queue2一個(gè)消息都會(huì)保存在Queue1结笨,Queue2包晰,Queue3,三個(gè)隊(duì)列中炕吸。這就是交換器的direct類型的路由規(guī)則伐憾。只要找到路由器與routingkey綁定的隊(duì)列,那么他有多少隊(duì)列赫模,他就分發(fā)給多少隊(duì)列树肃。
- Exchange類型fanout
這個(gè)類型忽略Routingkey,他為廣播模式瀑罗。
Note:消息從客戶端發(fā)出胸嘴,只要queue與exchange有綁定,那么他不管你的Routingkey是什么他都會(huì)將消息分發(fā)給所有與該exchang綁定的隊(duì)列中斩祭。
- Exchange類型topic
這個(gè)類型的路由規(guī)則如果你掌握啦劣像,那是相當(dāng)?shù)暮糜茫c靈活停忿。他是根據(jù)RoutingKey的設(shè)置驾讲,來做匹配的,其中這里還有兩個(gè)通配符為:
*,代表任意的一個(gè)詞吮铭。例如topic.zlh.*时迫,他能夠匹配到,topic.zlh.one ,topic.zlh.two ,topic.zlh.abc, ....
#谓晌,代表任意多個(gè)詞掠拳。例如topic.#,他能夠匹配到纸肉,topic.zlh.one ,topic.zlh.two ,topic.zlh.abc, ....
Note:這個(gè)圖看上去很亂溺欧,但是他是根據(jù)匹配符做匹配的,這里我建議你自己做下消息隊(duì)列的具體操作柏肪。
-
Headers Exchange
headers 也是根據(jù)規(guī)則匹配, 相較于 direct 和 topic 固定地使用 routing_key , headers 則是一個(gè)自定義匹配規(guī)則的類型.
在隊(duì)列與交換器綁定時(shí), 會(huì)設(shè)定一組鍵值對(duì)規(guī)則, 消息中也包括一組鍵值對(duì)( headers 屬性), 當(dāng)這些鍵值對(duì)有一對(duì), 或全部匹配時(shí), 消息被投送到對(duì)應(yīng)隊(duì)列.
5 消息隊(duì)列的消費(fèi)與消息確認(rèn)Ack
- 消息隊(duì)列的消費(fèi)
Note:如果一個(gè)消息隊(duì)列中有大量消息等待操作時(shí)姐刁,我們可以用多個(gè)客戶端來處理消息,這里的分發(fā)機(jī)制是采用負(fù)載均衡算法中的輪詢烦味。第一個(gè)消息給A聂使,下一個(gè)消息給B,下下一個(gè)消息給A谬俄,下下下一個(gè)消息給B......以此類推柏靶。
- 為啦保證消息的安全性,保證此消息被正確處理后才能在服務(wù)端的消息隊(duì)列中刪除溃论。那么rabbitmq提供啦ack應(yīng)答機(jī)制屎蜓,來實(shí)現(xiàn)這一功能。ack應(yīng)答有兩種方式:1钥勋、自動(dòng)應(yīng)答炬转,2、手動(dòng)應(yīng)答笔诵。
6 AMQP
AMQP(Advanced Message Queuing Protocol)協(xié)議是一個(gè)高級(jí)抽象層消息通信協(xié)議返吻,RabbitMQ是AMQP協(xié)議的實(shí)現(xiàn)。它主要包括以下組件:
- Server(broker): 接受客戶端連接乎婿,實(shí)現(xiàn)AMQP消息隊(duì)列和路由功能的進(jìn)程。
- Virtual Host:其實(shí)是一個(gè)虛擬概念街佑,類似于權(quán)限控制組谢翎,一個(gè)Virtual Host里面可以有若干個(gè)Exchange和Queue,但是權(quán)限控制的最小粒度是Virtual Host沐旨。
- Exchange:接受生產(chǎn)者發(fā)送的消息森逮,并根據(jù)Binding規(guī)則將消息路由給服務(wù)器中的隊(duì)列。ExchangeType決定了Exchange路由消息的行為磁携,例如褒侧,在RabbitMQ中,ExchangeType有direct、Fanout和Topic三種闷供,不同類型的Exchange路由的行為是不一樣的烟央。
- Message Queue:消息隊(duì)列,用于存儲(chǔ)還未被消費(fèi)者消費(fèi)的消息歪脏。
- Message: 由Header和Body組成疑俭,Header是由生產(chǎn)者添加的各種屬性的集合,包括Message是否被持久化婿失、由哪個(gè)Message Queue接受钞艇、優(yōu)先級(jí)是多少等。而Body是真正需要傳輸?shù)腁PP數(shù)據(jù)豪硅。
- Binding:Binding聯(lián)系了Exchange與Message Queue哩照。Exchange在與多個(gè)Message Queue發(fā)生Binding后會(huì)生成一張路由表,路由表中存儲(chǔ)著Message Queue所需消息的限制條件即Binding Key懒浮。當(dāng)Exchange收到Message時(shí)會(huì)解析其Header得到Routing Key葡秒,Exchange根據(jù)Routing Key與Exchange Type將Message路由到Message Queue。Binding Key由Consumer在Binding Exchange與Message Queue時(shí)指定嵌溢,而Routing Key由Producer發(fā)送Message時(shí)指定眯牧,兩者的匹配方式由Exchange Type決定。
- Connection:連接赖草,對(duì)于RabbitMQ而言学少,其實(shí)就是一個(gè)位于客戶端和Broker之間的TCP連接。
- Channel:信道秧骑,僅僅創(chuàng)建了客戶端到Broker之間的連接后版确,客戶端還是不能發(fā)送消息的。需要為每一個(gè)Connection創(chuàng)建Channel乎折,AMQP協(xié)議規(guī)定只有通過Channel才能執(zhí)行AMQP的命令绒疗。一個(gè)Connection可以包含多個(gè)Channel。之所以需要Channel骂澄,是因?yàn)門CP連接的建立和釋放都是十分昂貴的吓蘑,如果一個(gè)客戶端每一個(gè)線程都需要與Broker交互,如果每一個(gè)線程都建立一個(gè)TCP連接坟冲,暫且不考慮TCP連接是否浪費(fèi)磨镶,就算操作系統(tǒng)也無法承受每秒建立如此多的TCP連接。RabbitMQ建議客戶端線程之間不要共用Channel健提,至少要保證共用Channel的線程發(fā)送消息必須是串行的琳猫,但是建議盡量共用Connection。
- Command:AMQP的命令私痹,客戶端通過Command完成與AMQP服務(wù)器的交互來實(shí)現(xiàn)自身的邏輯脐嫂。例如在RabbitMQ中统刮,客戶端可以通過publish命令發(fā)送消息,txSelect開啟一個(gè)事務(wù)账千,txCommit提交一個(gè)事務(wù)侥蒙。
在了解了AMQP模型以后,需要簡單介紹一下AMQP的協(xié)議棧蕊爵,AMQP協(xié)議本身包括三層:
- Module Layer辉哥,位于協(xié)議最高層,主要定義了一些供客戶端調(diào)用的命令攒射,客戶端可以利用這些命令實(shí)現(xiàn)自己的業(yè)務(wù)邏輯醋旦,例如,客戶端可以通過queue.declare聲明一個(gè)隊(duì)列会放,利用consume命令獲取一個(gè)隊(duì)列中的消息饲齐。
- Session Layer,主要負(fù)責(zé)將客戶端的命令發(fā)送給服務(wù)器咧最,在將服務(wù)器端的應(yīng)答返回給客戶端捂人,主要為客戶端與服務(wù)器之間通信提供可靠性、同步機(jī)制和錯(cuò)誤處理矢沿。
- Transport Layer滥搭,主要傳輸二進(jìn)制數(shù)據(jù)流,提供幀的處理捣鲸、信道復(fù)用瑟匆、錯(cuò)誤檢測(cè)和數(shù)據(jù)表示。
7 RabbitMQ使用場景
場景1:單發(fā)送單接收
使用場景:簡單的發(fā)送與接收栽惶,沒有特別的處理愁溜。
場景2:單發(fā)送多接收
使用場景:一個(gè)發(fā)送端,多個(gè)接收端外厂,如分布式的任務(wù)派發(fā)冕象。為了保證消息發(fā)送的可靠性,不丟失消息汁蝶,使消息持久化了渐扮。同時(shí)為了防止接收端在處理消息時(shí)down掉,只有在消息處理完成后才發(fā)送ack消息穿仪。
發(fā)送端和場景1不同點(diǎn):
- 使用“task_queue”聲明了另一個(gè)Queue席爽,因?yàn)镽abbitMQ不容許聲明2個(gè)相同名稱、配置不同的Queue
- 使"task_queue"的Queue的durable的屬性為true啊片,即使消息隊(duì)列durable
- 使用MessageProperties.PERSISTENT_TEXT_PLAIN使消息durable
接收端和場景1不同點(diǎn):
- 使用“task_queue”聲明消息隊(duì)列,并使消息隊(duì)列durable
- 在使用channel.basicConsume接收消息時(shí)使autoAck為false玖像,即不自動(dòng)會(huì)發(fā)ack紫谷,由channel.basicAck()在消息處理完成后發(fā)送消息齐饮。
- 使用了channel.basicQos(1)保證在接收端一個(gè)消息沒有處理完時(shí)不會(huì)接收另一個(gè)消息,即接收端發(fā)送了ack后才會(huì)接收下一個(gè)消息笤昨。在這種情況下發(fā)送端會(huì)嘗試把消息發(fā)送給下一個(gè)not busy的接收端祖驱。
場景3:Publish/Subscribe
使用場景:發(fā)布、訂閱模式瞒窒,發(fā)送端發(fā)送廣播消息捺僻,多個(gè)接收端接收。
發(fā)送端:
發(fā)送消息到一個(gè)名為“l(fā)ogs”的exchange上崇裁,使用“fanout”方式發(fā)送匕坯,即廣播消息,不需要使用queue拔稳,發(fā)送端不需要關(guān)心誰接收葛峻。
接收端:
- 聲明名為“l(fā)ogs”的exchange的,方式為"fanout"巴比,和發(fā)送端一樣术奖。
- channel.queueDeclare().getQueue();該語句得到一個(gè)隨機(jī)名稱的Queue,該queue的類型為non-durable轻绞、exclusive采记、auto-delete的,將該queue綁定到上面的exchange上接收消息政勃。
- 注意binding queue的時(shí)候唧龄,channel.queueBind()的第三個(gè)參數(shù)Routing key為空,即所有的消息都接收稼病。如果這個(gè)值不為空选侨,在exchange type為“fanout”方式下該值被忽略!
場景4:Routing (按路線發(fā)送接收)
使用場景:發(fā)送端按routing key發(fā)送消息然走,不同的接收端按不同的routing key接收消息援制。
發(fā)送端和場景3的區(qū)別:
- exchange的type為direct
- 發(fā)送消息的時(shí)候加入了routing key
接收端和場景3的區(qū)別:
在綁定queue和exchange的時(shí)候使用了routing key,即從該exchange上只接收routing key指定的消息芍瑞。
場景5:Topics (按topic發(fā)送接收)
使用場景:發(fā)送端不只按固定的routing key發(fā)送消息晨仑,而是按字符串“匹配”發(fā)送,接收端同樣如此拆檬。
發(fā)送端和場景4的區(qū)別:
- exchange的type為topic
- 發(fā)送消息的routing key不是固定的單詞洪己,而是匹配字符串,如".lu.#"竟贯,匹配一個(gè)單詞答捕,#匹配0個(gè)或多個(gè)單詞。
接收端和場景4的區(qū)別:
- exchange的type為topic
- 接收消息的routing key不是固定的單詞屑那,而是匹配字符串拱镐。