一、寫在前面 使用過分散式中間件的人都知道,程式員使用起來並不複雜,常用的客戶端 API 就那麼幾個,比我們日常編寫程式時用到的 API 要少得多。但是分散式中間件在中小研發團隊中使用得並不多,為什麼會這樣呢? 原因是中間件的職責相對單一,客戶端的使用雖然簡單,但整個環境搭起來卻不容易。所以對於系列 ...
一、寫在前面
使用過分散式中間件的人都知道,程式員使用起來並不複雜,常用的客戶端 API 就那麼幾個,比我們日常編寫程式時用到的 API 要少得多。但是分散式中間件在中小研發團隊中使用得並不多,為什麼會這樣呢?
原因是中間件的職責相對單一,客戶端的使用雖然簡單,但整個環境搭起來卻不容易。所以對於系列中的幾篇中間件文章,我們重點放在解決門檻問題,把服務端環境搭好(後期可雲或運維解決),把中間件的基本職責和功能介紹好,把客戶端 Demo 寫好,讓程式員抬抬腳,在調試代碼中即可輕鬆入門。
根據我們以往幾年的經驗,初次接觸也可以自主快速學習,文章和 Demo 以實用為主,以下是消息隊列 RabbitMQ 的快速入門及應用。
二、為什麼要用消息隊列 MQ
1、業務系統往往要求響應能力特別強,能夠起到削峰填谷的作用。
2、解耦:如果一個系統掛了,則不會影響另外系統的繼續運行。
3、業務系統往往有對消息的高可靠要求,以及有對複雜功能如 Ack 的要求。
4、增強業務系統的非同步處理能力,減少甚至幾乎不可能出現併發現象:
使用消息隊列,就好比為了防汛而建葛洲壩,有大量數據的堆積能力,然後可靠地進行非同步輸出。例如:
傳統做法存在如下問題,請見上圖:
- 一旦業務處理時間超過了定時器時間間隔,就會導致漏單。
- 如果採用新開線程的方式獲取數據,那麼由於大量新開線程處理,會容易造成伺服器宕機。
- 資料庫壓力大,易併發。
使用 MQ 後的好處,請見上圖:
- 業務可註冊、可配置。
- 獲取數據規則可配置。
- 成功消費 MQ 中的消息才會被 Ack,提高可靠性。
- 大大增強了非同步處理業務作業的能力:
定時從資料庫獲取數據後,存入 MQ 消息隊列,然後 Job 會定期掃描 MQ 消息隊列,假設 Job 掃描後先預取 5 條消息,然後非同步處理這 5 條消息,也就是說這 5 條消息可能會同時被處理。
三、RabbitMQ 簡介
RabbitMQ 是基於 AMQP 實現的一個開源消息組件,主要用於在分散式系統中存儲轉發消息,由因高性能、高可用以及高擴展而出名的 Erlang 語言寫成。
其中,AMQP(Advanced Message Queuing Protocol,即高級消息隊列協議),是一個非同步消息傳遞所使用的應用層協議規範,為面向消息的中間件設計。
RabbitMQ 特點如下:
高可靠:RabbitMQ 提供了多種多樣的特性讓你在可靠性和性能之間做出權衡,包括持久化、發送應答、發佈確認以及高可用性。
高可用隊列:支持跨機器集群,支持隊列安全鏡像備份,消息的生產者與消費者不論哪一方出現問題,均不會影響消息的正常發出與接收。
靈活的路由:所有的消息都會通過路由器轉發到各個消息隊列中,RabbitMQ 內建了幾個常用的路由器,並且可以通過路由器的組合以及自定義路由器插件來完成複雜的路由功能。
支持多客戶端:對主流開發語言(如:Python、Ruby、.NET、Java、C、PHP、ActionScript 等)都有客戶端實現。
集群:本地網路內的多個 Server 可以聚合在一起,共同組成一個邏輯上的 broker。
擴展性:支持負載均衡,動態增減伺服器簡單方便。
許可權管理:靈活的用戶角色許可權管理,Virtual Host 是許可權控制的最小粒度。
插件系統:支持各種豐富的插件擴展,同時也支持自定義插件,其中最常用的插件是 Web 管理工具 RabbitMQ_Management,可參考如下文章:https://www.cnblogs.com/gossip/p/4475978.html
四、RabbitMQ 工作原理
消息從發送端到接收端的流轉過程即 RabbitMQ 的消息工作機制,請見下圖:
消息發送與接收的工作機制
五、RabbitMQ 基本用法
共有 6 種基本用法:單對單、單對多、發佈訂閱模式、按路由規則發送接收、主題、RPC(即遠程存儲調用)。我們將介紹單對單、單對多和主題的用法。
1、單對單:單發送、單接收。請見下圖。
2、單對多:一個發送端,多個接收端,如分散式的任務派發。請見下圖:
3、主題:Exchange Type 為 topic,發送消息時需要指定交換機及 Routing Key,消費者的消息隊列綁定到該交換機並匹配到 Routing Key 實現消息的訂閱,訂閱後則可接收消息。只有消費者將隊列綁定到該交換機且指定的 Routing Key 符合匹配規則,才能收到消息。
其中 Routing Key 可以設置成通配符,如:*或 #(*表示匹配 Routing Key 中的某個單詞,# 表示任意的 Routing Key 的消息都能被收到)。如果 Routing Key 由多個單片語成,則單詞之間用. 來分隔。
命名規範:
交換機名的命名建議:Ex{AppID}.{自定義 ExchangeName},隊列名的命名建議:MQ{AppID}.{自定義 QueueName} 。
六、Demo 下載及更多資料
RabbitMQDemo 下載地址:https://github.com/das2017/RabbitMQDemo
RabbitMQ 的官方網址:http://www.rabbitmq.com