學(xué)習(xí)完整課程請移步 互聯(lián)網(wǎng) Java 全棧工程師
本節(jié)視頻
什么是 MQ
Message Queue(MQ),消息隊(duì)列中間件。很多人都說:MQ 通過將消息的發(fā)送和接收分離來實(shí)現(xiàn)應(yīng)用程序的異步和解偶春寿,這個(gè)給人的直覺是——MQ 是異步的寿羞,用來解耦的袁梗,但是這個(gè)只是 MQ 的效果而不是目的细燎。MQ 真正的目的是為了通訊适滓,屏蔽底層復(fù)雜的通訊協(xié)議铝穷,定義了一套應(yīng)用層的钠怯、更加簡單的通訊協(xié)議。一個(gè)分布式系統(tǒng)中兩個(gè)模塊之間通訊要么是 HTTP曙聂,要么是自己開發(fā)的 TCP晦炊,但是這兩種協(xié)議其實(shí)都是原始的協(xié)議。HTTP 協(xié)議很難實(shí)現(xiàn)兩端通訊——模塊 A 可以調(diào)用 B,B 也可以主動(dòng)調(diào)用 A断国,如果要做到這個(gè)兩端都要背上 WebServer贤姆,而且還不支持長連接(HTTP 2.0 的庫根本找不到)。TCP 就更加原始了稳衬,粘包庐氮、心跳、私有的協(xié)議宋彼,想一想頭皮就發(fā)麻弄砍。MQ 所要做的就是在這些協(xié)議之上構(gòu)建一個(gè)簡單的“協(xié)議”——生產(chǎn)者/消費(fèi)者模型。MQ 帶給我的“協(xié)議”不是具體的通訊協(xié)議输涕,而是更高層次通訊模型音婶。它定義了兩個(gè)對象——發(fā)送數(shù)據(jù)的叫生產(chǎn)者;接收數(shù)據(jù)的叫消費(fèi)者莱坎, 提供一個(gè) SDK 讓我們可以定義自己的生產(chǎn)者和消費(fèi)者實(shí)現(xiàn)消息通訊而無視底層通訊協(xié)議
有 Broker 的 MQ
這個(gè)流派通常有一臺服務(wù)器作為 Broker衣式,所有的消息都通過它中轉(zhuǎn)。生產(chǎn)者把消息發(fā)送給它就結(jié)束自己的任務(wù)了檐什,Broker 則把消息主動(dòng)推送給消費(fèi)者(或者消費(fèi)者主動(dòng)輪詢)
重 Topic
kafka碴卧、JMS(ActiveMQ)就屬于這個(gè)流派,生產(chǎn)者會發(fā)送 key 和數(shù)據(jù)到 Broker乃正,由 Broker 比較 key 之后決定給哪個(gè)消費(fèi)者住册。這種模式是我們最常見的模式,是我們對 MQ 最多的印象瓮具。在這種模式下一個(gè) topic 往往是一個(gè)比較大的概念荧飞,甚至一個(gè)系統(tǒng)中就可能只有一個(gè) topic,topic 某種意義上就是 queue名党,生產(chǎn)者發(fā)送 key 相當(dāng)于說:“hi叹阔,把數(shù)據(jù)放到 key 的隊(duì)列中”
如上圖所示,Broker 定義了三個(gè)隊(duì)列传睹,key1耳幢,key2,key3欧啤,生產(chǎn)者發(fā)送數(shù)據(jù)的時(shí)候會發(fā)送 key1 和 data睛藻,Broker 在推送數(shù)據(jù)的時(shí)候則推送 data(也可能把 key 帶上)。
雖然架構(gòu)一樣但是 kafka 的性能要比 jms 的性能不知道高到多少倍堂油,所以基本這種類型的 MQ 只有 kafka 一種備選方案修档。如果你需要一條暴力的數(shù)據(jù)流(在乎性能而非靈活性)那么 kafka 是最好的選擇
輕 Topic
這種的代表是 RabbitMQ(或者說是 AMQP)碧绞。生產(chǎn)者發(fā)送 key 和數(shù)據(jù)府框,消費(fèi)者定義訂閱的隊(duì)列,Broker 收到數(shù)據(jù)之后會通過一定的邏輯計(jì)算出 key 對應(yīng)的隊(duì)列,然后把數(shù)據(jù)交給隊(duì)列
這種模式下解耦了 key 和 queue迫靖,在這種架構(gòu)中 queue 是非常輕量級的(在 RabbitMQ 中它的上限取決于你的內(nèi)存)院峡,消費(fèi)者關(guān)心的只是自己的 queue;生產(chǎn)者不必關(guān)心數(shù)據(jù)最終給誰只要指定 key 就行了系宜,中間的那層映射在 AMQP 中叫 exchange(交換機(jī))照激。
AMQP 中有四種 exchange
- Direct exchange:key 就等于 queue
- Fanout exchange:無視 key,給所有的 queue 都來一份
- Topic exchange:key 可以用“寬字符”模糊匹配 queue
- Headers exchange:無視 key盹牧,通過查看消息的頭部元數(shù)據(jù)來決定發(fā)給那個(gè) queue(AMQP 頭部元數(shù)據(jù)非常豐富而且可以自定義)
這種結(jié)構(gòu)的架構(gòu)給通訊帶來了很大的靈活性俩垃,我們能想到的通訊方式都可以用這四種 exchange 表達(dá)出來。如果你需要一個(gè)企業(yè)數(shù)據(jù)總線(在乎靈活性)那么 RabbitMQ 絕對的值得一用
無 Broker 的 MQ
無 Broker 的 MQ 的代表是 ZeroMQ汰寓。該作者非常睿智口柳,他非常敏銳的意識到——MQ 是更高級的 Socket,它是解決通訊問題的有滑。所以 ZeroMQ 被設(shè)計(jì)成了一個(gè)“庫”而不是一個(gè)中間件跃闹,這種實(shí)現(xiàn)也可以達(dá)到——沒有 Broker 的目的
節(jié)點(diǎn)之間通訊的消息都是發(fā)送到彼此的隊(duì)列中,每個(gè)節(jié)點(diǎn)都既是生產(chǎn)者又是消費(fèi)者毛好。ZeroMQ 做的事情就是封裝出一套類似于 Socket 的 API 可以完成發(fā)送數(shù)據(jù)望艺,讀取數(shù)據(jù)
ZeroMQ 其實(shí)就是一個(gè)跨語言的、重量級的 Actor 模型郵箱庫肌访。你可以把自己的程序想象成一個(gè) Actor找默,ZeroMQ 就是提供郵箱功能的庫;ZeroMQ 可以實(shí)現(xiàn)同一臺機(jī)器的 RPC 通訊也可以實(shí)現(xiàn)不同機(jī)器的 TCP吼驶、UDP 通訊啡莉,如果你需要一個(gè)強(qiáng)大的、靈活旨剥、野蠻的通訊能力咧欣,別猶豫 ZeroMQ