RabbitMQ是目前非常熱門的一款消息中間件,不管是網際網路大廠還是中小企業都在大量使用。作為一名合格的開發者,有必要對RabbitMQ有所了解,本文是RabbitMQ快速入門文章,主要内容包括RabbitMQ是什麼、RabbitMQ核心概念、常用交換器類型、用Docker安裝RabbitMQ等。
以熟悉的電商場景為例,如果商品服務和訂單服務是兩個不同的微服務,在下單的過程中訂單服務需要調用商品服務進行扣庫存操作。按照傳統的方式,下單過程要等到調用完畢之後才能傳回下單成功,如果網絡産生波動等原因使得商品服務扣庫存延遲或者失敗,會帶來較差的使用者體驗,如果在高并發的場景下,這樣的處理顯然是不合适的,那怎麼進行優化呢?這就需要消息隊列登場了。
消息隊列提供一個異步通信機制,消息的發送者不必一直等待到消息被成功處理才傳回,而是立即傳回。消息中間件負責處理網絡通信,如果網絡連接配接不可用,消息被暫存于隊列當中,當網絡暢通的時候在将消息轉發給相應的應用程式或者服務,當然前提是這些服務訂閱了該隊列。如果在商品服務和訂單服務之間使用消息中間件,既可以提高并發量,又降低服務之間的耦合度。
RabbitMQ就是這樣一款我們苦苦追尋的消息隊列。RabbitMQ是一個開源的消息代理的隊列伺服器,用來通過普通協定在完全不同的應用之間共享資料。
RabbitMQ是使用Erlang語言來編寫的,并且RabbitMQ是基于AMQP協定的。Erlang語言在資料互動方面性能優秀,有着和原生Socket一樣的延遲,這也是RabbitMQ高性能的原因所在。可謂“人如其名”,RabbitMQ像兔子一樣迅速。
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiInBnaukTN3EzM3YTO00iN5kDNyMTNwEDMycDM5EDMy0SOwYDOzUTMvw1NwkTMwIzLclDM2gzM1EzLcd2bsJ2Lc12bj5ycn9Gbi52YugTMwIzZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
RabbitMQ除了像兔子一樣跑的很快以外,還有這些特點:
開源、性能優秀,穩定性保障
提供可靠性消息投遞模式、傳回模式
與Spring AMQP完美整合,API豐富
叢集模式豐富,表達式配置,HA模式,鏡像隊列模型
保證資料不丢失的前提做到高可靠性、可用性
MQ典型應用場景:
異步處理。把消息放入消息中間件中,等到需要的時候再去處理。
流量削峰。例如秒殺活動,在短時間内通路量急劇增加,使用消息隊列,當消息隊列滿了就拒絕響應,跳轉到錯誤頁面,這樣就可以使得系統不會因為超負載而崩潰。
日志處理
應用解耦。假設某個服務A需要給許多個服務(B、C、D)發送消息,當某個服務(例如B)不需要發送消息了,服務A需要改代碼再次部署;當新加入一個服務(服務E)需要服務A的消息的時候,也需要改代碼重新部署;另外服務A也要考慮其他服務挂掉,沒有收到消息怎麼辦?要不要重新發送呢?是不是很麻煩,使用MQ釋出訂閱模式,服務A隻生産消息發送到MQ,B、C、D從MQ中讀取消息,需要A的消息就訂閱,不需要了就取消訂閱,服務A不再操心其他的事情,使用這種方式可以降低服務或者系統之間的耦合。
提到RabbitMQ,就不得不提AMQP協定。AMQP協定是具有現代特征的二進制協定。是一個提供統一消息服務的應用層标準進階消息隊列協定,是應用層協定的一個開放标準,為面向消息的中間件設計。
先了解一下AMQP協定中間的幾個重要概念:
Server:接收用戶端的連接配接,實作AMQP實體服務。
Connection:連接配接,應用程式與Server的網絡連接配接,TCP連接配接。
Channel:信道,消息讀寫等操作在信道中進行。用戶端可以建立多個信道,每個信道代表一個會話任務。
Message:消息,應用程式和伺服器之間傳送的資料,消息可以非常簡單,也可以很複雜。有Properties和Body組成。Properties為外包裝,可以對消息進行修飾,比如消息的優先級、延遲等進階特性;Body就是消息體内容。
Virtual Host:虛拟主機,用于邏輯隔離。一個虛拟主機裡面可以有若幹個Exchange和Queue,同一個虛拟主機裡面不能有相同名稱的Exchange或Queue。
Exchange:交換器,接收消息,按照路由規則将消息路由到一個或者多個隊列。如果路由不到,或者傳回給生産者,或者直接丢棄。RabbitMQ常用的交換器常用類型有direct、topic、fanout、headers四種,後面詳細介紹。
Binding:綁定,交換器和消息隊列之間的虛拟連接配接,綁定中可以包含一個或者多個RoutingKey。
RoutingKey:路由鍵,生産者将消息發送給交換器的時候,會發送一個RoutingKey,用來指定路由規則,這樣交換器就知道把消息發送到哪個隊列。路由鍵通常為一個“.”分割的字元串,例如“com.rabbitmq”。
Queue:消息隊列,用來儲存消息,供消費者消費。
我們完全可以直接使用 Connection 就能完成信道的工作,為什麼還要引入信道呢?
試想這樣一個場景, 一個應用程式中有很多個線程需要從 RabbitMQ 中消費消息,或者生産消息,那麼必然需要建立很多個 Connection,也就是許多個 TCP 連接配接。然而對于作業系統而言,建立和銷毀 TCP 連接配接是非常昂貴的開銷,如果遇到使用高峰,性能瓶頸也随之顯現。 RabbitMQ 采用 TCP 連接配接複用的方式,不僅可以減少性能開銷,同時也便于管理 。
下圖是AMQP的協定模型:
正如圖中所看到的,AMQP協定模型有三部分組成:生産者、消費者和服務端。
生産者是投遞消息的一方,首先連接配接到Server,建立一個連接配接,開啟一個信道;然後生産者聲明交換器和隊列,設定相關屬性,并通過路由鍵将交換器和隊列進行綁定。同理,消費者也需要進行建立連接配接,開啟信道等操作,便于接收消息。
接着生産者就可以發送消息,發送到服務端中的虛拟主機,虛拟主機中的交換器根據路由鍵選擇路由規則,然後發送到不同的消息隊列中,這樣訂閱了消息隊列的消費者就可以擷取到消息,進行消費。
最後還要關閉信道和連接配接。
RabbitMQ是基于AMQP協定實作的,其結構如下圖所示,和AMQP協定簡直就是一模一樣。
RabbitMQ常用的交換器類型有direct、topic、fanout、headers四種。
Direct Exchange
該類型的交換器将所有發送到該交換器的消息被轉發到RoutingKey指定的隊列中,也就是說路由到BindingKey和RoutingKey完全比對的隊列中。
Topic Exchange
該類型的交換器将所有發送到Topic Exchange的消息被轉發到所有RoutingKey中指定的Topic的隊列上面。
Exchange将RoutingKey和某Topic進行模糊比對,其中“”用來比對一個詞,“#”用于比對一個或者多個詞。例如“com.#”能比對到“com.rabbitmq.oa”和“com.rabbitmq”;而"login."隻能比對到“com.rabbitmq”。
Fanout Exchange
該類型不處理路由鍵,會把所有發送到交換器的消息路由到所有綁定的隊列中。優點是轉發消息最快,性能最好。
Headers Exchange
該類型的交換器不依賴路由規則來路由消息,而是根據消息内容中的headers屬性進行比對。headers類型交換器性能差,在實際中并不常用。
在雲計算和容器技術大熱的今天,不會Docker顯得未免太out了吧。Docker提供一種安全、可重複的環境中自動部署軟體的方式,本文使用Docker進行安裝RabbitMQ。
進入官方下載下傳位址,選擇使用Docker安裝,跳轉到dockerhub檢視鏡像。
我選擇3.8.0-beta.4-management進行安裝,帶有management是含有管理界面的。
拉取鏡像和啟動:<code>docker run -d --hostname my-rabbit -p 5672:5672 -p 15672:15672 rabbitmq:3.8.0-beta.4-management</code>
檢視鏡像:
打開浏覽器通路localhost:15672,如果你和我一樣裝在虛拟機上面的話,需要打開虛拟機ip:15672
進行填寫賬号密碼:預設賬号密碼都是guest.
到此,RabbitMQ已經安裝并運作起來了。
本文介紹了RabbitMQ是什麼、RabbitMQ核心概念、常用交換器類型、用Docker安裝RabbitMQ等内容,看完本文,想必對于RabbitMQ已經有了一些初步的了解了,後面的世界更精彩。
本文參考慕課網免費課程:《RabbitMQ消息中間件極速入門與實戰》。
由于部落客也是在攀登的路上,文中可能存在不當之處,歡迎各位多指教! 如果文章對您有用,那麼請點個”推薦“,以資鼓勵!