“RabbitMQ?”“Kafka?”“RocketMQ?”...在日常學(xué)習(xí)與開發(fā)過程中,我們常常聽到消息隊列這個關(guān)鍵詞。
“RabbitMQ?”“Kafka?”“RocketMQ?”...在日常學(xué)習(xí)與開發(fā)過程中,我們常常聽到消息隊列這個關(guān)鍵詞。
現(xiàn)在只要是稍大的平臺都要考慮大數(shù)據(jù)高并發(fā)的問題、集群的問題、
負(fù)載均衡的問題;那么消息隊列在解決這類問題上占著舉足輕重的地位;比方說小伙伴們常常使用的火車票購票軟件
12306就使用到了消息隊列;所以消息隊列的學(xué)習(xí)和掌握是作為一個高級開發(fā)者必備的技能了。
如果你是老手,你可能從本文學(xué)到你之前不曾注意的一些關(guān)于消息隊列的重要概念,如果你是新手,相信本文將是你打開消息隊列大門的一板磚。
什么是消息隊列
“消息隊列”是在消息的傳輸過程中保存消息的容器。
當(dāng)一大批客戶端同時產(chǎn)生大量的網(wǎng)絡(luò)請求(消息)時候,服務(wù)器的承受能力肯定是有一個限制的。這時候要是有個容器,先讓這些消息排隊就好了,還好有個叫隊列的數(shù)據(jù)結(jié)構(gòu),通過有隊列屬性的容器排隊(先進先出),把消息再傳到我們的服務(wù)器,壓力減小了好多,這個很棒的容器就是消息隊列。
消息隊列優(yōu)勢
· 應(yīng)用解耦
消息隊列可以使消費者和生產(chǎn)者直接互不干涉,互不影響,只需要把消息發(fā)送到隊列即可,而且可獨立的擴展或修改兩邊的處理過程,只要能確保它們遵守同樣的接口約定,可以生產(chǎn)者用Node.js實現(xiàn),消費者用python實現(xiàn)。
· 靈活性和峰值處理能力
當(dāng)客戶端訪問量突然劇增,對服務(wù)器的訪問已經(jīng)超過服務(wù)所能處理的最大峰值,甚至導(dǎo)致服務(wù)器超時負(fù)載崩潰,使用消息隊列可以解決這個問題,可以通過控制消費者的處理速度和生產(chǎn)者可進入消息隊列的數(shù)量等來避免峰值問題排序保證消息隊列可以控制數(shù)據(jù)處理的順序,因為消息隊列本身使用的是隊列這個數(shù)據(jù)結(jié)構(gòu),FIFO(先進選出),在一些場景數(shù)據(jù)處理的順序很重要,比如商品下單順序等。
· 異步通信
消息隊列中的有些消息,并不需要立即處理,消息隊列提供了異步處理機制,可以把消息放在隊列中并不立即處理,需要的時候處理,或者異步慢慢處理,一些不重要的發(fā)送短信和郵箱功能可以使用。
· 可擴展性
前面提到了消息隊列可以做到解耦,如果我們想增強消息入隊和出隊的處理頻率,很簡單,并不需要改變代碼中任何內(nèi)容,可以直接對消息隊列修改一些配置即可,比如我們想限制每次發(fā)送給消費者的消息條數(shù)等。
RabbitMQ 特點
· RabbitMQ 是一個由 Erlang 語言開發(fā)的 AMQP 的開源實現(xiàn)。
· AMQP :Advanced Message Queue,高級消息隊列協(xié)議。它是應(yīng)用層協(xié)議的一個開放標(biāo)準(zhǔn),為面向消息的中間件設(shè)計,基于此協(xié)議的客戶端與消息中間件可傳遞消息,并不受產(chǎn)品、開發(fā)語言等條件的限制。
· RabbitMQ 最初起源于金融系統(tǒng),用于在分布式系統(tǒng)中存儲轉(zhuǎn)發(fā)消息,在易用性、擴展性、高可用性等方面表現(xiàn)不俗。具體特點包括:
· 可靠性(Reliability)RabbitMQ 使用一些機制來保證可靠性,如持久化、傳輸確認(rèn)、發(fā)布確認(rèn)。
· 靈活的路由(Flexible Routing)在消息進入隊列之前,通過 Exchange 來路由消息的。對于典型的路由功能,RabbitMQ 已經(jīng)提供了一些內(nèi)置的 Exchange 來實現(xiàn)。針對更復(fù)雜的路由功能,可以將多個 Exchange 綁定在一起,也通過插件機制實現(xiàn)自己的 Exchange 。
· 消息集群(Clustering)多個 RabbitMQ 服務(wù)器可以組成一個集群,形成一個邏輯 Broker 。
· 高可用(Highly Available Queues)隊列可以在集群中的機器上進行鏡像,使得在部分節(jié)點出問題的情況下隊列仍然可用。
· 多種協(xié)議(Multi-protocol)RabbitMQ 支持多種消息隊列協(xié)議,比如 STOMP、MQTT 等等。
· 多語言客戶端(Many Clients)RabbitMQ 幾乎支持所有常用語言,比如 Java、.NET、Ruby 等等。
· 管理界面(Management UI)RabbitMQ 提供了一個易用的用戶界面,使得用戶可以監(jiān)控和管理消息 Broker 的許多方面。
· 跟蹤機制(Tracing)如果消息異常,RabbitMQ 提供了消息跟蹤機制,使用者可以找出發(fā)生了什么。
· 插件機制(Plugin System)RabbitMQ 提供了許多插件,來從多方面進行擴展,也可以編寫自己的插件。
RabbitMQ 中的概念
· 消息模型
所有 MQ 產(chǎn)品從模型抽象上來說都是一樣的過程:消費者(consumer)訂閱某個隊列。生產(chǎn)者(producer)創(chuàng)建消息,然后發(fā)布到隊列(queue)中,最后將消息發(fā)送到監(jiān)聽的消費者。
· RabbitMQ 基本概念
上面只是最簡單抽象的描述,具體到 RabbitMQ 則有更詳細(xì)的概念需要解釋。上面介紹過 RabbitMQ 是 AMQP 協(xié)議的一個開源實現(xiàn),所以其內(nèi)部實際上也是 AMQP 中的基本概念:
· Message消息,消息是不具名的,它由消息頭和消息體組成。消息體是不透明的,而消息頭則由一系列的可選屬性組成,這些屬性包括routing-key(路由鍵)、priority(相對于其他消息的優(yōu)先權(quán))、delivery-mode(指出該消息可能需要持久性存儲)等。
· Publisher消息的生產(chǎn)者,也是一個向交換器發(fā)布消息的客戶端應(yīng)用程序。
· Exchange交換器,用來接收生產(chǎn)者發(fā)送的消息并將這些消息路由給服務(wù)器中的隊列。
· Binding綁定,用于消息隊列和交換器之間的關(guān)聯(lián)。一個綁定就是基于路由鍵將交換器和消息隊列連接起來的路由規(guī)則,所以可以將交換器理解成一個由綁定構(gòu)成的路由表。
· Queue消息隊列,用來保存消息直到發(fā)送給消費者。它是消息的容器,也是消息的終點。一個消息可投入一個或多個隊列。消息一直在隊列里面,等待消費者連接到這個隊列將其取走。
· Connection網(wǎng)絡(luò)連接,比如一個TCP連接。
· Channel信道,多路復(fù)用連接中的一條獨立的雙向數(shù)據(jù)流通道。信道是建立在真實的TCP連接內(nèi)的虛擬連接,AMQP 命令都是通過信道發(fā)出去的,不管是發(fā)布消息、訂閱隊列還是接收消息,這些動作都是通過信道完成。因為對于操作系統(tǒng)來說建立和銷毀 TCP 都是非常昂貴的開銷,所以引入了信道的概念,以復(fù)用一條 TCP 連接。
· Consumer消息的消費者,表示一個從消息隊列中取得消息的客戶端應(yīng)用程序。
· Virtual Host虛
擬主機,表示一批交換器、消息隊列和相關(guān)對象。
虛擬主機是共享相同的身份認(rèn)證和加密環(huán)境的
獨立服務(wù)器域。每個
vhost 本質(zhì)上就是一個 mini 版的 RabbitMQ 服務(wù)器,擁有自己的隊列、交換器、綁定和權(quán)限機制。vhost 是 AMQP 概念的基礎(chǔ),必須在連接時指定,RabbitMQ 默認(rèn)的 vhost 是 / 。
· Broker表示消息隊列服務(wù)器實體。
AMQP 中的消息路由
· AMQP 中消息的路由過程和 Java 開發(fā)者熟悉的 JMS 存在一些差別,AMQP 中增加了 Exchange 和 Binding 的角色。生產(chǎn)者把消息發(fā)布到 Exchange 上,消息最終到達(dá)隊列并被消費者接收,而 Binding 決定交換器的消息應(yīng)該發(fā)送到那個隊列。
AMQP 的消息路由過程
· Exchange 類型
· Exchange分發(fā)消息時根據(jù)類型的不同分發(fā)策略有區(qū)別,目前共四種類型:direct、fanout、topic、headers 。headers 匹配 AMQP 消息的 header 而不是路由鍵,此外 headers 交換器和 direct 交換器完全一致,但性能差很多,目前幾乎用不到了,所以直接看另外三種類型:
· directdirect 交換器消息中的路由鍵(routing key)如果和 Binding 中的 binding key 一致,交換器就將消息發(fā)到對應(yīng)的隊列中。路由鍵與隊列名完全匹配,如果一個隊列綁定到交換機要求路由鍵為“dog”,則只轉(zhuǎn)發(fā) routing key 標(biāo)記為“dog”的消息,不會轉(zhuǎn)發(fā)“dog.puppy”,也不會轉(zhuǎn)發(fā)“dog.guard”等等。它是完全匹配、單播的模式。
· fanoutfanout 交換器每個發(fā)到 fanout 類型交換器的消息都會分到所有綁定的隊列上去。fanout 交換器不處理路由鍵,只是簡單的將隊列綁定到交換器上,每個發(fā)送到交換器的消息都會被轉(zhuǎn)發(fā)到與該交換器綁定的所有隊列上。很像子網(wǎng)廣播,每臺子網(wǎng)內(nèi)的主機都獲得了一份復(fù)制的消息。fanout 類型轉(zhuǎn)發(fā)消息是最快的。
· topictopic 交換器topic 交換器通過模式匹配分配消息的路由鍵屬性,將路由鍵和某個模式進行匹配,此時隊列需要綁定到一個模式上。它將路由鍵和綁定鍵的字符串切分成單詞,這些單詞之間用點隔開。它同樣也會識別兩個通配符:符號“#”和符號“”。#匹配0個或多個單詞,匹配不多不少一個單詞。
RabbitMQ 安裝
· 一般來說安裝 RabbitMQ 之前要安裝 Erlang ,可以去Erlang官網(wǎng)下載。接著去RabbitMQ官網(wǎng)下載安裝包,之后解壓縮即可。根據(jù)操作系統(tǒng)不同官網(wǎng)提供了相應(yīng)的安裝說明:Windows、Debian / Ubuntu、RPM-based Linux、Mac
· 如果是Mac 用戶,個人推薦使用 HomeBrew 來安裝,安裝前要先更新 brew:
· brew update
· 接著安裝 rabbitmq 服務(wù)器:
· brew install rabbitmq
· 這樣 RabbitMQ 就安裝好了,安裝過程中會自動其所依賴的 Erlang 。