楔子:項目中,開發很容易忽視的一點是,只想到或者只想做自己應該做的事。這是非常有礙自己進步和自我放棄的一個心態或決策。實際上,只要你置身於萬物中,每個層階都是這樣。所以,相比拎包入住的租賃市場的成熟與便利,開包即用的項目開發,是團隊協作的精華,而我們要做的就是製作那些精華。
1. 枯燥無味
不管是單擊遊戲,還是喫雞遊戲,拋開主觀情感,其路子本質基本上都是打怪升級成就無量至尊。所以,無論是主線還是支線任務,是副本還是打野,攢經驗升級前,我們先要做的基本上都是 是什麼、爲什麼、做什麼、怎麼做(用)、怎麼做(用)能快速高效等等,只是遊戲讓這些問題都變得潛移默化順乎所以。
那 MQ 是什麼?我爲什麼要 Get 她?她能做什麼?我要怎麼做/用?什麼時候用?怎麼做/用可以更快速高效?
理論的產生從是來枯燥無味,不妨讓理解理論的過程變得有趣一點。
2. 大水池子
我們可以想像有一個大水池子,裏面的水時而被使用殆盡,時而又被注入新水,常此以往,這池水物澤蒼生大地經久不息。而注入新水爲生產者(Producer)、使用水源爲消費者(Consumer),這個大水池子就是服務器(Name Server、Broker),大水池2、大水池3 ... 的互通就是服務器集羣,消費工具就是水管管道(訂閱 Topic)。
- 居民區B對水池2的消費使用突增,水池1、水池3的水源會互通調節注入,以防水池2被使用乾涸,這可以理解爲服務器的削峯填谷。
- 居民區B的B001戶人家使用大水池的水,並不會影響居民區A的A001戶人家;且B001戶人家要開始洗衣做飯拖地啦。這個指令一下,洗衣機要用水開始洗衣,廚房要放水洗菜洗碗,陽臺要放水洗拖把,但是並不會相互產生制約,因爲沒有隻能洗衣放水而做飯停水,也沒有隻能洗菜有水而洗拖把沒水的顧慮。這就是異步解耦。
- 順序消息也好理解,比如B001戶的小朋友哭着要喫牛奶了,這個指令的前置條件是奶粉+溫開水,開水不行,小朋友馬上就要喝的,冷水也不行,所以這個收到泡牛奶的消息後,指令就可以拆解爲 涼白開 + 開水 + 奶粉 + 輕搖溶解 + 試溫 一系列操作後才能給小朋友喝。不然,小朋友不會喝,還哭得更厲害。抑或者洗澡,我們肯定是要在抹完沐浴露後再用水沖洗身子,再用幹浴巾擦,最後穿上衣服,而不是抹完沐浴露後不衝也不擦直接穿衣服。這就是完成一條指令信息遵循的先後動作,顛倒不得。
- 分佈式事務消息可以想像成B001戶做中飯,這個信息指令可以分工拆解快速的完成:小朋友他爸放水淘米煮飯,小朋友他媽放水洗菜,小朋友奶奶炒菜,小朋友爺爺帶娃,這樣的流程下來,一家人就可以很快喫到一桌好飯好菜了。相比奶奶一個人帶娃又淘米洗菜炒菜要方便快捷得不要太多。
這就是 RocketMQ 的特性和應用場景。
3. 生而不凡
3.1. 那 MQ 是什麼?
記憶中第一次玩遊戲時,對 RPG 這個名詞陌生又熟悉,但我知道自己在玩一款 角色扮演遊戲(Role-playing game,簡稱 RPG)。瞭解一個事物一般是從 TA 的名字或名稱開始的,也有從印象從感覺開始的,但是也有很多例外,像花兒,像TA,像MQ。
消息隊列(Message Queue,簡稱 MQ),是構建分佈式互聯網應用的基礎設施,通過 MQ 實現的松耦合架構設計可以提高系統可用性以及可擴展性,既可爲分佈式應用系統提供異步解耦和削峯填谷的能力,同時也具備互聯網應用所需的海量消息堆積、高吞吐、可靠重試等特性。是適用於現代應用的最佳設計方案。具體常見的有如訂單消息,支付消息等等。
3.2. 什麼是 RocketMQ 呢?
就像你在瞭解 TRPG (桌上角色扮演遊戲,Table-top Role-Playing Game);SRPG (策略角色扮演遊戲,Strategy Role-Playing Game) 一樣,RocketMQ 也是 MQ 消息隊列家庭中的一個系,因爲除了 RocketMQ,還有 RabbitMQ、Kafka、MQTT 等等。
Apache RocketMQ 是由阿里巴巴自研,並捐贈給 Apache 基金會,並於開源社區共建的消息中間件,2017年9月25日成爲 Apache 的頂級項目。該產品服務於阿里巴巴集團已超過 13 年,經過交易核心鏈路反覆打磨與歷年雙十一高併發場景的嚴苛考驗,已然是一個真正具備低延遲、高併發、高可用、高可靠,可支撐萬億級數據洪峯的分佈式消息中間件。
RocketMQ 經歷了三個主要版本迭代:
- Metaq(Metamorphosis) 1.x
由開源社區 killme2008(莊曉丹)維護,最後一次 MetaQ 的更新時間爲2013年。 - Metaq 2.x
於2012 年10 月份上線,在淘寶內部被廣泛使用。 - RocketMQ 3.x
基於阿里巴巴公司內部開源共建原則,RocketMQ 項目只維護核心功能,且去除了所有其他運行時依賴,核心功能最簡化。每個產品的個性化需求都在 RocketMQ 項目之上進行深度定製。
官網:http://rocketmq.apache.org
下載:http://rocketmq.apache.org/dowloading/releases/
GitHub:https://github.com/apache/rocketmq
3.3. 你的名字
做任務,不管是主線還是支線,你都需要在遊戲裏面找到具體某個“人”(NPC);AT 代表攻擊力(Attack);DF 代表防禦力(Defense)等等,玩遊戲也要玩得得心應手玩得專業的話,就不免需要了解很多的遊戲專業術語。
瞭解 MQ 也是一樣,需要了解一些核心概念:
- 消息生產者(Producer):
負責生產消息,一般由業務系統負責生產消息。一個消息生產者會把業務應用系統裏產生的消息發送到 Broker 服務器。RocketMQ 提供多種發送方式:同步發送、異步發送、順序發送、單向發送。同步和異步方式均需要 Broker 返回確認信息,單向發送不需要。詳見第三節。 - 消息消費者(Consumer):
負責消費消息,一般是後臺系統負責異步消費。一個消息消費者會從 Broker 服務器拉取消息、並將其提供給應用程序。從用戶應用的角度而言提供了兩種消費形式:拉取式消費、推動式消費。詳見第三節。 - 主題(Topic):
表示一類消息的集合,每個主題包含若干條消息,每條消息只能屬於一個主題,是 RocketMQ 進行消息訂閱的基本單位。 - 標籤(Tag):
爲消息設置的標誌,用於同一主題下區分不同類型的消息。來自同一業務單元的消息,可以根據不同業務目的在同一主題下設置不同標籤。標籤能夠有效地保持代碼的清晰度和連貫性,並優化 RocketMQ 提供的查詢系統。消費者可以根據 Tag 實現對不同子主題的不同消費邏輯,實現更好的擴展性。 - 消息(Message):
消息系統所傳輸信息的物理載體,生產和消費數據的最小單位,每條消息必須屬於一個主題。RocketMQ 中每個消息擁有唯一的 Message ID,且可以攜帶具有業務標識的 Key。系統提供了通過 Message ID 和 Key 查詢消息的功能。 - 代理服務器(Broker Server):
消息中轉角色,負責存儲消息、轉發消息。代理服務器在 RocketMQ 系統中負責接收從生產者發送來的消息並存儲、同時爲消費者的拉取請求作準備。代理服務器也存儲消息相關的元數據,包括消費者組、消費進度偏移和主題和隊列消息等。 - 名字服務(Name Server):
名稱服務充當路由消息的提供者。生產者或消費者能夠通過名字服務查找各主題相應的 Broker IP 列表。多個 Namesrv 實例組成集羣,但相互獨立,沒有信息交換。 - 生產者組(Producer Group):
同一類 Producer 的集合,這類 Producer 發送同一類消息且發送邏輯一致。如果發送的是事物消息且原始生產者在發送之後崩潰,則 Broker 服務器會聯繫同一生產者組的其他生產者實例以提交或回溯消費。 - 消費者組(Consumer Group):
同一類 Consumer 的集合,這類 Consumer 通常消費同一類消息且消費邏輯一致。消費者組使得在消息消費方面,實現負載均衡和容錯的目標變得非常容易。要注意的是,消費者組的消費者實例必須訂閱完全相同的 Topic。RocketMQ 支持兩種消息模式:集羣消費(Clustering)和廣播消費(Broadcasting)。詳見第五節。
3.4. 那我爲什麼要 Get 到她呢?
就像在喫雞遊戲裏面你搞到一把98K狙擊步槍的狂肆;就像在誅仙遊戲裏你合成了一套+12裝備的狂喜;也像 MQ,她們功能特點和功能特點產生的作用或效果都會讓你狂浪。
RocketMQ 的主要特點有:
- 靈活可擴展性
RocketMQ 天然支持集羣,其核心四組件(Name Server、Broker、Producer、Consumer)每一個都可以在沒有單點故障的情況下進行水平擴展。 - 支持順序消息
可以保證消息消費者按照消息發送的順序對消息進行消費。順序消息分爲全局有序和局部有序,一般推薦使用局部有序,即生產者通過將某一類消息按順序發送至同一個隊列來實現。 - 支持事務消息
RocketMQ 除了支持普通消息,順序消息之外還支持事務消息,支持事務消息絕對是亮點,這個特性對於分佈式事務來說提供了一種最佳解決方案。 - 消息回溯消費
回溯消費是指消費者已經消費成功的消息,由於業務上需求需要重新消費,RocketMQ 支持按照時間回溯消費,時間維度精確到毫秒,可以向前回溯,也可以向後回溯。 - 多種消息過濾方式
5.1 消息過濾分爲在服務端過濾和在消費端過濾
5.2 服務端過濾時可以按照消息消費者的要求做過濾,優點是減少不必要消息傳輸,缺點是增加了消息服務器的負擔,實現相對複雜
5.3 消費端過濾則完全由具體應用自定義實現,這種方式更加靈活,缺點是很多無用的消息會傳輸給消息消費者 - 億級消息堆積能力
RocketMQ 採用零拷貝原理實現超大的消息的堆積能力,在堆積海量消息後依然保持寫入低延遲。
3.5. 她能做什麼?
RocketMQ 的應用場景非常多,主要是可以實現分佈式系統業務解耦:
- 削峯填谷:諸如秒殺、搶紅包、企業開門紅等大型活動時皆會帶來較高的流量脈衝,或因沒做相應的保護而導致系統超負荷甚至崩潰,或因限制太過導致請求大量失敗而影響用戶體驗,消息隊列 MQ 可提供削峯填谷的服務來解決該問題。
- 異步解耦:交易系統作爲淘寶/天貓主站最核心的系統,每筆交易訂單數據的產生會引起幾百個下游業務系統的關注,包括物流、購物車、積分、流計算分析等等,整體業務系統龐大而且複雜,消息隊列 MQ 可實現異步通信和應用解耦,確保主站業務的連續性。
- 順序收發:細數日常中需要保證順序的應用場景非常多,比如證券交易過程時間優先原則,交易系統中的訂單創建、支付、退款等流程,航班中的旅客登機消息處理等等。與先進先出(First In First Out,縮寫 FIFO)原理類似,消息隊列 MQ 提供的順序消息即保證消息 FIFO。
- 分佈式事務一致性:交易系統、支付紅包等場景需要確保數據的最終一致性,大量引入消息隊列 MQ 的分佈式事務,既可以實現系統之間的解耦,又可以保證最終的數據一致性。
- 大數據分析:數據在“流動”中產生價值,傳統數據分析大多是基於批量計算模型,而無法做到實時的數據分析,利用阿里雲消息隊列 MQ 與流式計算引擎相結合,可以很方便的實現將業務數據進行實時分析。
- 分佈式緩存同步:天貓雙 11 大促,各個分會場琳琅滿目的商品需要實時感知價格變化,大量併發訪問數據庫導致會場頁面響應時間長,集中式緩存因爲帶寬瓶頸限制商品變更的訪問流量,通過消息隊列 MQ 構建分佈式緩存,實時通知商品數據的變化。
4. 江湖奇才
RocketMQ 系統架構部署圖:
4.1. 系統架構
1)Producer:消息發佈的角色,支持分佈式集羣方式部署。Producer 通過 MQ 的負載均衡模塊選擇相應的 Broker 集羣隊列進行消息投遞,投遞的過程支持快速失敗並且低延遲。
2)Consumer:消息消費的角色,支持分佈式集羣方式部署。支持以 push 推,pull 拉兩種模式對消息進行消費。同時也支持集羣方式和廣播方式的消費,它提供實時消息訂閱機制,可以滿足大多數用戶的需求。
3)NameServer:NameServer 是一個非常簡單的 Topic 路由註冊中心,其角色類似 Dubbo 中的 zookeeper,支持 Broker 的動態註冊與發現。主要包括兩個功能:
- Broker 管理,NameServer 接受 Broker 集羣的註冊信息並且保存下來作爲路由信息的基本數據。然後提供心跳檢測機制,檢查 Broker 是否還存活;
- 路由信息管理,每個 NameServer 將保存關於 Broker 集羣的整個路由信息和用於客戶端查詢的隊列信息。然後 Producer 和 Conumser 通過 NameServer 就可以知道整個 Broker 集羣的路由信息,從而進行消息的投遞和消費。NameServer 通常也是集羣的方式部署,各實例間相互不進行信息通訊。Broker 是向每一臺 NameServer 註冊自己的路由信息,所以每一個 NameServer 實例上面都保存一份完整的路由信息。當某個 NameServer 因某種原因下線了,Broker 仍然可以向其它 NameServer 同步其路由信息,Producer、Consumer 仍然可以動態感知 Broker 的路由的信息。
4)BrokerServer:Broker 主要負責消息的存儲、投遞和查詢以及服務高可用保證,爲了實現這些功能,Broker 包含了以下幾個重要子模塊:
- Remoting Module:整個 Broker 的實體,負責處理來自 clients 端的請求。
- Client Manager:負責管理客戶端(Producer/Consumer)和維護 Consumer 的 Topic 訂閱信息
- Store Service:提供方便簡單的API接口處理消息存儲到物理硬盤和查詢功能。
- HA Service:高可用服務,提供 Master Broker 和 Slave Broker 之間的數據同步功能。
- Index Service:根據特定的 Message key 對投遞到 Broker 的消息進行索引服務,以提供消息的快速查詢。
4.2. 網絡部署
4.2.1 部署架構圖解
- Name Server:是一個幾乎無狀態節點,可集羣部署,在消息隊列 MQ 中提供命名服務,更新和發現 Broker 服務。
- Broker:消息中轉角色,負責存儲消息,轉發消息。分爲 Master Broker 和 Slave Broker,一個 Master Broker 可以對應多個 Slave Broker,但是一個 Slave Broker 只能對應一個 Master Broker。Broker 啓動後需要完成一次將自己註冊至 Name Server 的操作;隨後每隔 30s 定期向 Name Server 上報 Topic 路由信息。
- Producer:與 Name Server 集羣中的其中一個節點(隨機)建立長鏈接(Keep-alive),定期從 Name Server 讀取 Topic 路由信息,並向提供 Topic 服務的 Master Broker 建立長鏈接,且定時向 Master Broker 發送心跳。
- Consumer:與 Name Server 集羣中的其中一個節點(隨機)建立長連接,定期從 Name Server 拉取 Topic 路由信息,並向提供 Topic 服務的 Master Broker、Slave Broker 建立長連接,且定時向 Master Broker、Slave Broker 發送心跳。Consumer 既可以從 Master Broker 訂閱消息,也可以從 Slave Broker 訂閱消息,訂閱規則由 Broker 配置決定。
4.2.2 集羣工作流程
- 啓動 NameServer,NameServer 起來後監聽端口,等待 Broker、Producer、Consumer 連上來,相當於一個路由控制中心。
- Broker 啓動,跟所有的 NameServer 保持長連接,定時發送心跳包。心跳包中包含當前 Broker 信息(IP+端口等)以及存儲所有 Topic 信息。註冊成功後,NameServer 集羣中就有 Topic 跟 Broker 的映射關係。
- 收發消息前,先創建 Topic,創建 Topic 時需要指定該 Topic 要存儲在哪些 Broker 上,也可以在發送消息時自動創建 Topic。
- Producer 發送消息,啓動時先跟 NameServer 集羣中的其中一臺建立長連接,並從 NameServer 中獲取當前發送的 Topic 存在哪些 Broker 上,輪詢從隊列列表中選擇一個隊列,然後與隊列所在的 Broker 建立長連接從而向 Broker 發消息。
- Consumer 跟 Producer 類似,跟其中一臺 NameServer 建立長連接,獲取當前訂閱 Topic 存在哪些 Broker 上,然後直接跟 Broker 建立連接通道,開始消費消息。
注意:圖文中所提及的消息隊列 MQ 的服務端或者服務器包含 Name Server、Broker 等。服務端不等同於 Broker。
參考資料:
RocketMQ 官網:http://rocketmq.apache.org/docs/motivation/
阿里雲消息隊列 MQ:https://help.aliyun.com/document_detail/29532.html
阿里巴巴中間件團隊:http://jm.taobao.org/2017/03/03/RocketMQ-future-idea/
RocketMQ進擊物語:
RocketMQ進擊(零)RocketMQ這個大水池子
RocketMQ進擊(一)Windows環境下安裝部署Apache RocketMQ
RocketMQ進擊(二)一個默認生產者,兩種消費方式,三類普通消息詳解分析
RocketMQ進擊(三)順序消息與高速公路收費站
RocketMQ進擊(四)定時消息(延時隊列)
RocketMQ進擊(五)集羣消費模式與廣播消費模式
RocketMQ進擊(六)磕一磕RocketMQ的事務消息
RocketMQ進擊(七)盤一盤RocketMQ的重試機制
RocketMQ進擊(八)RocketMQ的日誌收集Logappender
RocketMQ異常:RocketMQ順序消息收不到或者只能收到一部分消息
RocketMQ異常:Unrecognized VM option 'MetaspaceSize=128m'