入門RabbitMQ消息隊列,看這篇文章就夠了

目錄

前言

什麼是隊列

什麼是消息隊列

什麼是RabbitMQ

消息隊列的應用場景

消息通訊

異步處理

服務解耦

流量削峯

RabbitMQ安裝與啓動

在Cnetos7上的安裝

         安裝

        安裝-detached爲可選參數,表示後臺開啓

Docker上的安裝

         啓動鏡像

核心概念

Broker

Producer與Consumer

Connection

Channel

Exchnage

Queue

Binding

Virtual Host

工作模式

簡單(simple)模式

工作(work)模式

發佈/訂閱(pub/sub)模式

路由(routing)模式

主題(topic)模式

幾種常見消息隊列的對比

小結


前言

關於消息隊列,筆者依稀記得多年前剛畢業實習的時候,由於業務上的需要,有過一段時間的研究,那時候研究的目的是要引入一個更好的消息隊列中間件來解決公司門店數據與總部機房數據通訊的問題,只可惜那時候筆者經驗尚淺,並沒有對消息隊列有更深入的理解。

不過出於開發的需要,最近又開始消息隊列的學習,並將學習筆記整理成這篇文章,以備查驗。

什麼是隊列

隊列(Queue)是一種常見的數據結構,其最大的特性就是先進先出(Firist In First Out),作爲最基礎的數據結構,隊列應用很廣泛,比如我們熟知的Redis基礎數據類型List,其底層數據結構就是隊列。

什麼是消息隊列

消息隊列(Messaeg Queue)是一種使用隊列(Queue)作爲底層存儲數據結構,可用於解決不同進程與應用之間通訊的分佈式消息容器,也稱爲消息中間件。

目前使用得比較多的消息隊列有ActiveMQRabbitMQKafkaRocketMQ等。

什麼是RabbitMQ

RabbitMQ是用Erlang語言開發的一個實現了AMQP協議的消息隊列服務器,相比其他同類型的消息隊列,最大的特點在保證可觀的單機吞吐量的同時,延時方面非常出色。

RabbitMQ支持多種客戶端,比如:PythonRuby.NETJavaJMSCPHPActionScriptXMPPSTOMP等。

AMQP,即Advanced Message Queuing Protocol,高級消息隊列協議,是應用層協議的一個開放標準,爲面向消息的中間件設計。

消息隊列的應用場景

消息隊列使用廣泛,其應用場景有很多,下面我們列舉比較常見的五個場景。

消息通訊

消息隊列最主要功能收發消息,其內部有高效的通訊機制,因此非常適合用於消息通訊。

我們可以基於消息隊列開發點對點聊天系統

也可以開發廣播系統,用於將消息廣播給大量接收者。

異步處理

一般我們寫的程序都是順序執行(同步執行),比如一個用戶註冊函數,其執行順序如下:

  • 1.寫入用戶註冊數據。

  • 2.發送註冊郵件。

  • 3.發送註冊成功的短信通知。

  • 4.更新統計數據。

按照上面的執行順序,要全部執行完畢,才能返回成功,但其實在第1步執行成功後,其他的步驟完全可以異步執行,我們可以將後面的邏輯發給消息隊列,再由其他程序異步執行,如下所示:

使用消息隊列進行異步處理,可以更快地返回結果,加快服務器的響應速度,提升了服務器的性能。

服務解耦

在我們的系統中,應用與應用之間的通訊是很常見的,一般我們應用之間直接調用,比如說應用A調用應用B的接口,這時候應用之間的關係是強耦合的。

如果應用B處於不可用的狀態,那麼應用A也會受影響。

在應用A與應用B之間引入消息隊列進行服務解耦,如果應用B掛掉,也不會影響應用A的使用。

流量削峯

對於高併發的系統來說,在訪問高峯時,突發的流量就像洪水般嚮應用系統湧過來,尤其是一些高併發寫操作,隨時會導致數據庫服務器癱瘓,無法繼續提供服務。

而引入消息隊列則可以減少突發流量對應用系統的衝擊。消息隊列就像“水庫”一樣,攔蓄上游的洪水,削減進入下游河道的洪峯流量,從而達到減免洪水災害的目的。

這方面最常見的例子就是秒殺系統,一般秒殺活動瞬間流量很高,如果流量全部湧向秒殺系統,會壓垮秒殺系統,通過引入消息隊列,可以有效緩衝突發流量,達到“削峯填谷”的作用。

RabbitMQ安裝與啓動

RabbitMQ支持LinuxWindowsUnixMacOS等多種操作系統,我們可以根據自己的操作系統來安裝對應的版本,下面我們只講解如何在Cnetos7上安裝,和使用Docker進行安裝。

更多安裝詳細信息,可查看官網

在Cnetos7上的安裝

下面演示ErlangRabbitMQ的安裝,我們使用rpm的一鍵安裝包,這種方式比較方便,比較適合初學者。

基礎依賴安裝

如果你的操作系統是Linux的最小安裝包,那麼應該有很多基礎的依賴包沒有安裝,在安裝RabbitMQ之前,需要安裝好這些基礎依賴包,可以運行如下命令:

$ sudo yum install openssql openssl-devel make gcc gcc-c++ kernel-devel
複製代碼

安裝Socat

RabbitMQ依賴於Socat,因此在安裝RabbitMQ前要安裝Socat,如下:

$ sudo yum install -y socat
複製代碼

安裝Erlang

因爲RabbitMQ是用Erlang語言開發,所以在安裝RabbitMQ前,要先安裝Erlang運行環境,我們使用Erlang語言的rpm安裝包。

# 下載
$ wget https://github.com/rabbitmq/erlang-rpm/releases/download/v22.3/erlang-22.3-1.el7.x86_64.rpm

安裝

複製代碼

$ rpm -ivh erlang-22.3-1.el7.x86_64.rpm 複製代碼

 

安裝RabbitMQ

上面所說的依賴安裝完成後,最後我們可以運行下面的命令安裝RabbitMQ:

# 下載
$ wget https://github.com/rabbitmq/rabbitmq-server/releases/download/v3.8.3/rabbitmq-server-3.8.3-1.el7.noarch.rpm

安裝

複製代碼

$ rpm -ivh rabbitmq-server-3.8.3-1.el7.noarch.rpm 複製代碼

 

啓動與關閉

安裝完成之後,可以使用rabbitmq-server命令啓動服務器,如下:

# 直接啓動
$ sudo rabbitmq-server

-detached爲可選參數,表示後臺開啓

複製代碼

$ sudo rabbitmq-server -detached 複製代碼

 

啓動成功,輸出如下:

如果要關閉,則可以使用下面的命令:

#關閉RabbitMQ服務:  
$ sudo rabbitmqctl stop  
複製代碼

插件管理

上面我們使用rabbitmq-server啓動服務器,也可以使用rabbitmqctl命令管理服務器,包括創建交換機、隊列、用戶管理等操作,除了命令管理工具,RabbitMQ還提供了Web管理工具,而Web管理工具作爲RabbitMQ的插件,如果要開啓,可以使用下面的命令 :

rabbitmq-plugins是RabbitMQ管理插件的命令。

$ sudo rabbitmq-plugins enable rabbitmq_management 
複製代碼

啓動插件後,我們再啓動服務器,最後一行顯示運行了3個插件,如下:

重新啓動服務器後,可以打開瀏覽器訪問RabbitMQ的Web管理界面

Web管理程序的端口號是15672,在瀏覽器中輸入http://localhost:15672,即可以訪問。

Docker上的安裝

上面演示的是直接在操作系統上安裝RabbitMQ的過程,如果你本地有安裝Docker運行環境,那麼可以下載RabbitMQDocker鏡像進行安裝,這種方式很方便,也不需要自己安裝RabbitMQ依賴。

可以Docker Hub上查詢我們需要的RabbitMQ鏡像包,如下:

我們選擇以tag帶management後綴的鏡像, 這表示該版本帶有Web管理界面。

# 拉取鏡像包
docker pull rabbitmq:3.8.3-management

啓動鏡像

複製代碼

docker run -d --name rabbitmq -p 5672:5672 -p 15672:15672 -v pwd複製代碼/data:/var/lib/rabbitmq --hostname myRabbit -e RABBITMQ_DEFAULT_VHOST=my_vhost -e RABBITMQ_DEFAULT_USER=admin -e RABBITMQ_DEFAULT_PASS=admin rabbitmq3.8.3-management 複製代碼

 

核心概念

RabbitMQ有屬於自己的一套核心概念,對這些概念的理解很重要,只有理解了這些核心概念,纔有可能建立對RabbitMQ的全面理解。

Broker

Broker概念比較簡單,我們可以把Broker理解爲一個RabitMQ Server

Producer與Consumer

生產者與消費者相對於RabbitMQ服務器來說,都是RabbitMQ服務器的客戶端。

  • 生產者(Producer):連到RabbitMQ服務器,將消息發送到RabbitMQ服務器的隊列,是消息的發送方。

  • 消費者(Consumer):連接到RabbitMQ則是爲了消費隊列中的消息,是消息的接收方。

生產者與消費者一般由我們的應用程序充當。

Connection

ConnectionRabbitMQ內部對象之一,用於管理每個到RabbitMQTCP網絡連接。

Channel

Channel是我們與RabbitMQ打交道的最重要的一個接口,我們大部分的業務操作是在Channel這個接口中完成的,包括定義Queue、定義Exchange、綁定QueueExchange、發佈消息等

Exchnage

消息交換機,作用是接收來自生產者的消息,並根據路由鍵轉發消息到所綁定的隊列。

生產者發送上的消息,就是先通過Exchnage按照綁定(binding)規則轉發到隊列的。

交換機類型(Exchange Type)有四種:fanoutdirecttopicheaders,其中headers並不常用。

  • fanout:這種類型不處理路由鍵(RoutingKey),很像子網廣播,每臺子網內的主機都獲得了一份複製的消息,發佈/訂閱模式就是指使用fanout交換機類型,fanout類型交換機轉發消息是最快的。

  • direct:模式處理路由鍵,需要路由鍵完全匹配的隊列才能收到消息,路由模式使用的是direct類型的交換機。

  • topic:將路由鍵和某模式進行匹配。主題模式使用的是topic類型的交換機。

路由模式,發佈訂閱模式,主題模式,這些工作模式我們下面會講。

Queue

Queue,即隊列,RabbitMQ內部用於存儲消息的對象,是真正用存儲消息的結構,在生產端,生產者的消息最終發送到指定隊列,而消費者也是通過訂閱某個隊列,達到獲取消息的目的。

Binding

Binding是一種操作,其作用是建立消息從Exchange轉發到Queue的規則,在進行ExchangeQueue的綁定時,需要指定一個BindingKey,Binding操作一般用於RabbitMQ的路由工作模式和主題工作模式。

BindingKey的概念,我們下面在講RabbitMQ的工作模式會詳細講解。

Virtual Host

Virutal host也叫虛擬主機,一個VirtualHost下面有一組不同ExchnageQueue,不同的Virtual hostExchnageQueue之間互相不影響。

應用隔離與權限劃分,Virtual host是RabbitMQ中最小顆粒的權限單位劃分。

如果要類比的話,我們可以把Virtual host比作MySQL中的數據庫,通常我們在使用MySQL時,會爲不同的項目指定不同的數據庫,同樣的,在使用RabbitMQ時,我們可以爲不同的應用程序指定不同的Virtual host

上面我們一一列舉了RabbitMQ的核心概念,通過下面的示意圖,我們可以更清晰地瞭解它們之間的關係。

工作模式

RabbitMQ一共有六種工作模式,分別爲簡單模式、工作隊列模式、發佈/訂閱模式、路由模式、主題模式和RPC模式,RPC模式並不常用,因此我們下面只講前面五種工作模式。

簡單(simple)模式

simple模式,是RabbitMQ幾種模式中最簡單的一種模式,其結構如下圖所示:

從上面的示意圖,我們可以看出simple模式有以下幾個特徵:

  • 只有一個生產者、一個消費者和一個隊列。

  • 生產者和消費者在發送和接收消息時,只需要指定隊列名,而不需要指定發送到哪個ExchangeRabbitMQ服務器會自動使用Virtual host的默認的Exchange,默認Exchangetypedirect

工作(work)模式

simple模式下只有一個生產者和消費者,當生產者生產消息的速度大於消費者的消費速度時,我們可以添加一個或多個消費者來加快消費速度,這種在simple模式下增加消費者的模式,稱爲work模式,如下圖所示:

work模式有以下兩個特徵:

  • 可以有多個消費者,但一條消息只能被一個消費者獲取。

  • 發送到隊列中的消息,由服務器平均分配給不同消費者進行消費。

發佈/訂閱(pub/sub)模式

work模式可以將消息轉到多個消費者,但每條消息只能由一個消費者獲取,如果我們想一條消息可以同時給多個消費者消費呢?

這時候就需要發佈/訂閱模式,其示意圖如下所示:

從上面的示意圖我們可以看出來,在發佈/訂閱模式下,需要指定發送到哪個Exchange中,上面圖中的X表示Exchange

  • 發佈/訂閱模式中,Echangetypefanout

  • 生產者發送消息時,不需要指定具體的隊列名,Exchange會將收到的消息轉發到所綁定的隊列。

  • 消息被Exchange轉到多個隊列,一條消息可以被多個消費者獲取。

路由(routing)模式

前面幾種模式,消息的目標隊列無法由生產者指定,而在路由模式下,消息的目標隊列,可以由生產者指定,其示意圖如下所示:

從上面示意圖,我們可以看出路由模式有以下特徵:

  • 路由模式下Exchange的type爲direct

  • 消息的目標隊列可以由生產者按照routingKey規則指定。

  • 消費者通過BindingKey綁定自己所關心的隊列。

  • 一條消息隊可以被多個消息者獲取。

  • 只有RoutingKeyBidingKey相匹配的隊列纔會收到消息。

RoutingKey用於生產者指定Exchange最終將消息路由到哪個隊列,BindingKey用於消費者綁定到某個隊列。

主題(topic)模式

主題模式是在路由模式的基礎上,將路由鍵和某模式進行匹配。其中#表示匹配多個詞,*表示匹配一個詞,消費者可以通過某種模式的BindKey來達到訂閱某個主題消息的目的,如示意圖如下所示:

  • 主題模式Exchange的type取值爲topic。

  • 一條消息可以被多個消費者獲取。

幾種常見消息隊列的對比

除了RabbitMQ之外,還有其他比較常見的消息隊列中間件,如KafkaRocketMQActiveMQ等,下面的表格中列舉了這幾種消息隊列的差異:

消息隊列 RabbitMQ ActiveMQ RocketMQ Kafka
所屬公司/社區 Mozilla Public License Apache Ali Apache
成熟度 成熟 成熟 比較成熟 成熟
授權方式 開源 開源 開源 開源
開發語言 Erlang Java Java Scala & Java
客戶端支持語言 官方支持Erlang,java,Ruby等,社區產出多種語言API,幾乎支持所有常用語言 JAVA,C++,pyhton,php,perl,net等 java,c++ 官方支持java,開源社區有多種語言版本,如PHP,python,go,c/c++,ruby,node.js等語言
協議支持 多協議支持AMQP,XMPP,SMTP,STOMP OpenWire,STOMP,REST,XMPP/AMOP 自定義的一套 自定義協議
消息批量操作 不支持 支持 支持 支持
消息推拉模式 多協議,pull/push均有支持 多協議pull/push均有支持 多協議,pull/push均有支持 pull
HA master/slave模式 基於zookeeper+LevelDB的master-slave 支持多master模式,多master多slave模式,異步複製模式 支持replica機制,leader宕掉後,備份自動頂替,並重新選擇leader
數據可靠性 可以保證數據不丟,有slave備份 master/slave 支持異步實時刷盤,同步刷盤,同步複製,民步複製 數據可靠,並且有replica機制,有容錯容災能力
單機吞吐量 其次(萬級) 最差(萬級) 最高(十萬級) 次之(十萬級)
消息延遲 微秒級 \ 比Kafka快 毫秒級
持久化能力 內存、文件、支持數據堆積,但數據堆積反過來影響生產速率 內存、文件、數據庫 碰盤文件 磁盤文件 磁盤文件,只要磁盤容量夠,可以做到無限消息堆積
是否有序 若想有序,只能使用一個client 可以支持有序 有序 多client保證有序
事務 支持 支持 支持 不支持
集羣 支持 支持 支持 支持
負載均衡 支持 支持 支持 支持
管理界面 較好 一般 命令行界面 官方只提供了命令行版
部署方式 獨立 獨立 獨立 獨立

小結

本文講解了隊列與RabbitMQ的概念、如何安裝RabbitMQRabbitMQ的核心概念以及幾種工作模式,由於涉及到RabbitMQ的大部分知識點,因此鑑於筆者水平有限,文章中講解不對或不足的地方,歡迎指出,不勝感激!

瞭解更多內容,請關注微信公衆號【程序員Style】,回覆“666”,領取各語言的電子書、視頻等學習資料。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章