1.消息隊列介紹
消息隊列本質上來講是一個符合先進先出原則的單向隊列:一方發送消息並存入消息隊列尾部(生產者投遞消息),一方從消息隊列的頭部取出消息(消費者消費消息)。但對於一個成熟可靠的消息隊列來講,所須要解決的主要問題還包括:高效可靠的消息投遞、存儲;能承受高併發的流量衝擊,可經過集羣部署來解決單點故障等等。html
因爲消息隊列具有了以上特色,所以在現在的微服務架構中可以做爲一種中間件,提供許多重要的功能以解決微服務架構中的諸多痛點:java
1.應用解耦
微服務架構中,存在着衆多子系統,共同完成對外部用戶的服務。linux
舉個例子:當用戶在訂單系統下單時,訂單子系統除了須要執行本身系統的業務邏輯以外,可能還須要調用庫存子系統去扣減庫存;調用會員子系統去增長用戶的積分;調用數據分析子系統去插入用戶下單的分析數據等等。用戶的一個下單行爲橫跨了N個業務子系統,若是按照傳統的同步串行方式一個接一個的調用,用戶的下單操做將會執行較長的時間,對用戶不友好。同時,因爲是同步調用,一旦某一個子系統出現了宕機,訪問超時等問題,整個下單業務都將陷入癱瘓。shell
消息隊列能夠將同步的系統調用轉爲異步的消息投遞,必定程度上解除業務子系統間的耦合。當訂單子系統執行完本地邏輯後,只需發送一個標識下單成功的消息,讓下游依賴的子系統訂閱此消息,消費處理消息來完成對應的業務。這樣,用戶的下單操做將很快完成,也沒必要擔憂下游子系統的故障會波及到訂單系統。apache
雖然消息隊列解除了業務子系統間的耦合,但同時也讓業務子系統對消息隊列系統有了很強的依賴關係,若是消息隊列出現了故障,業務系統將會出現嚴重故障。windows
但因爲消息隊列在設計之初的目的十分簡單明確:就是爲了可靠的收發消息。所以其可用性,穩定性比絕大多數業務系統要高的多。天下沒有免費的午飯,在微服務系統中引入消息隊列依然是利大於弊的。緩存
2.流量削峯
大多數系統的訪問流量並非一天24小時均勻穩定的,而是存在着必定的突發性。例如電商的秒殺活動,系統配置在平時能承受住500qps,可在進行秒殺活動時,瞬時的qps可能達到了5000,爲日常的10倍,若是不進行處理防禦,將會致使服務癱瘓。服務器
能夠選擇擴容服務器來應對可能的高峯流量,但擴容的服務器在秒殺活動過去以後多數會被閒置,從而形成很大的浪費;也能夠設定併發的閾值,在訪問併發數達到必定程度時就進行熔斷限流,拒絕手慢的秒殺用戶下單,可這樣會讓用戶體驗不好。架構
這時,消息隊列就能派上用場了。咱們能夠在系統中使用消息隊列做爲緩衝,將每個用戶下單請求都做爲一條消息存入消息隊列,消息隊列會根據消費者的消費速度以一種穩定的方式將流量傳遞給下游消費者系統,在消費者系統處理完下單操做後異步的通知用戶下單結果。雖然用戶可能會延遲一段時間才能獲得反饋,但不管如何也比沒法下單要好。併發
消息隊列就像一個漏桶,能夠將瞬時的尖峯流量緩存起來,並以一種穩定的速度傳遞給下游消費者,從而達到流量削峯的目的。
3.消息分發
沿用以前的例子,訂單子系統的下單成功操做在業務上可能有許多其它系統須要對其作出響應(扣庫存,加積分,覈銷優惠券等等)。
按照傳統的方式,須要訂單系統挨個調用其它子系統的接口。隨着業務的變化,每當有新的子系統須要對下單成功操做作出響應時,就須要改動訂單系統的代碼邏輯去適應新的需求。
而若是引入了消息隊列,則能夠在下單成功以後由訂單系統發送一條消息,讓感興趣的其它子系統去訂閱下單成功消息。若是新的系統也出現了依賴下單成功動做的需求,自行訂閱對應消息便可,並不須要訂單系統作出任何的改變。
能夠利用消息分發機制能夠實現代碼邏輯的解耦。
2.Rocketmq介紹
rocketmq是阿里巴巴團隊使用java語言開發的一款分佈式消息中間件,是一款低延遲,高可用,擁有海量消息堆積能力和靈活拓展性的消息隊列。
2.1 rocketmq組成部分
rocketmq由四大核心模塊組成:producer、consumer、brokerServer、nameServer。其中brokerServer和nameServer是rocketmq的服務端,二者一塊兒獨立的對外提供服務;而producer和consumer可看作是rocketmq的客戶端,通常依附於業務應用程序。
1. Producer
producer負責發送消息。使用producer將消息發送到brokerServer,由brokerServer統一進行消息的分發。
rocketmq支持多種消息發送方式,如同步消息發送、異步回調消息發送、順序消息發送以及單向消息發送(異步無回調)。除了單向消息發送,其他的發送方式均須要brokerServer返回發送結果的確認消息。
特別的,rocketmq的一大特點是支持發送事務消息(半消息),能必定程度上解決分佈式事務的問題。
2. Consumer
consumer 負責消費producer發送的消息。consumer會從brokerServer獲取消息,並傳遞給應用程序。
rocketMQ使用的消息原語是At Least Once(至少一次成功消費),若是必定時間內沒有接收到consumer消息確認消費的響應結果,會將同一條消息再次投遞給consumer。rocketmq採用ack機制保證消息的消費成功,因此consumer可能會屢次收到同一條消息,須要consumer的業務方作好冪等防禦。
從使用者的角度來看,consumer分爲兩種方式來獲取信息。一種是推模式(push consume),推模式看起來像是brokerServer將消息推給了consumer;另外一種是拉模式(pull consume),拉模式看起來像是consumer主動的去brokerServer拉取消息(實際上,推模式是基於拉模式實現的)。
3. BrokerServer
brokerServer負責消息的接收,存儲和分發,是rocketmq最核心,最重量級的組成部分。
爲實現高可用和高吞吐,brokerServer一般採用集羣部署,共同對外提供服務。
4. NameServer
nameServer負責提供路由元數據。例如,brokerServer一般是集羣部署的,其拓撲結構會常常的發生變化。若是每次集羣中broker機器的上下線都須要通知全部的消費者、生產者,效率過低。
所以,rocketmq引入了nameServer做爲brokerServer路由信息的維護者,broker的每次上下線都和nameServer通訊,由nameServer來維護broker的路由信息,而producer和consumer經過訪問nameServer得到對應broker的訪問地址後,再向對應的broker發起請求。nameServer解除了broker和客戶端的耦合依賴關係,大大提升了效率。
在其它主流消息隊列中也存在着相似的維護元信息功能的組件,如zookeeper等。rocketmq的設計者認爲zk的功能過於強大,殺雞焉用牛刀,經過一個精簡版的元數據服務nameServer,以減小對外部系統的耦合依賴,得以提供更可靠的服務。
nameServer一樣能以集羣形式對外提供服務。但和zk集羣不一樣的是,集羣內的nameServer服務器並不會互相通訊,而是保持相互獨立。
2.2 rocketmq基本概念模型
介紹完rocketmq的組成部分以後,還須要再引入一些相關概念才能更好的理解rocketmq:
1.topic 主題
topic主題,表明一系列消息的集合,任何消息只能屬於一個topic主題,主題是rocketmq進行消息發佈訂閱的最小單位。業務方能夠經過建立並訂閱各式各樣的主題來知足自身的業務要求。不一樣主題之間的消息在邏輯上沒有關聯。
2.tag 標籤
tag標籤,tag從屬於topic主題,主要用於對同一主題下的消息進行進一步區分。標籤能夠簡單的認爲是二級主題,經過tag標籤功能,業務方能夠方便的實現對各類二級主題的消費需求。
3.group 組
group組,表明着同一類客戶端的集合。具體可分爲消費者組(consumer group)和生產者組(producer group)兩種。消費者組和生產者組之間沒有任何關聯(即便組名同樣)。
消費者組:
消費者組表明着同一類型的消費者集羣。同一消費者組內的消費者一般消費一樣的消息且消息消費邏輯一致。消費者組的概念使得consumer集羣在消費消息時,rocketmq能夠經過負載均衡來作到消費消息時的高可用和容錯。消費者組的更多做用將會在後面的集羣/廣播消費模式中繼續講解。
生產者組:
生產者組表明着同一類型的生產者集羣。通常來講,消息的生產者在發出了消息獲得確認以後便完成了任務,彷佛沒有必要爲此抽象出生產者集羣的概念。
前面說到,rocketmq具備發送事務消息的特性,發送事務消息簡單來講就是生產者先發送出一個半消息(預消息),而後執行本地的事務,在事務完成提交以後再跟着發送一個事務確認消息。半消息和普通消息的最大區別在於,半消息在投遞給broker以後,broker不會立刻讓消費者進行消費,而是等待。只有當接收到生產者後續對應的的事務確認消息後,預消息和確認消息合二爲一,纔將對應的事務消息交給消費者去消費;而若是最終沒有接收到事務確認消息,則會將消息直接刪除不投遞給消費者,以達到相似事務回滾的效果。事務消息對消費者來講是透明無感知的。
可若是生產者在發送了預消息以後掛了怎麼辦?爲解決這個問題,broker會在必定時間沒有收到確認消息後,定時的回查生產者當前事務消息的狀態,回查的範圍是整個生產者組中的某一個在線節點。這種狀況下,生產者和消費者同樣,也構成了一個集羣監聽來自broker的回查。這樣,即便發送消息的生產者發生了故障,在必定條件下整個生產者集羣的事務消息發送功能依然能夠正常運轉。
經過生產者組的概念,rocketmq實現了事務消息投遞的高可用。
4.message 消息
message消息是rocketmq中傳遞消息的主體,消息具備全局惟一的messageID屬性,用戶能夠根據messageID查詢進行消息的精確查詢。
消息的內容能夠是不超過rocketmq限制的、二進制的任意數據,rocketmq不會對消息承載的數據內容作任何干預。
5. 集羣(Clustering)/廣播(Broadcasting)消費
集羣消費:
對於任意一條被訂閱的消息,同一消費者組下的節點只有一個節點對其進行消費;一個消費者組中的所有節點分攤全部消息。
廣播消費:
對於任意一條被訂閱的消息,同一消費者組下的全部節點都會對其進行消費;一個消費者組中的所有節點都能接收到全量的消息。
混合模式消費:
實質上是前二者的綜合。同一應用集羣構成一個消費者組,不一樣應用集羣之間構成多個不一樣的消費者組,但卻能夠訂閱同一個topic/tag下的消息。
對於任意一條被訂閱的消息,同一消費者組之間只會有一個節點對其進行消費,不一樣消費者組都會進行全量消息的消費。
3.Rocketmq下載與安裝
介紹了rocketmq的一些基本概念以後,下面進行rocketmq的下載和安裝,並進行基本的功能測試。簡單起見,nameServer,broker都以單機模式啓動。
注意:示例中新版本的rocketmq要求jvm的最低版本是1.8。
3.1 從官網下載資源
首先在rocketmq的官網能夠找到下載資源,其中有已經編譯完成的二進制資源(binary)和須要用戶本身編譯的源代碼資源(source)兩種。在這裏選擇下載已經編譯完成的,更容易上手的二進制資源進行安裝。
3.2 配置rocketmq環境變量
將下載好的資源解壓縮到任意目錄,能夠看到以下文件夾和文件,其中命令行的腳本文件都集中放在bin文件夾下。(這裏是windows環境下的操做,資源包中也包含了linux下一樣功能的shell腳本文件,操做並無明顯差別)
因爲腳本文件依賴一個叫作ROCKETMQ_HOME的環境變量,代指rocketmq安裝的主目錄,所以咱們須要配置ROCKETMQ_HOME環境變量。
3.3 啓動nameServer
開啓一個新的命令行窗口用於啓動nameServer,將命令行路徑指向bin文件目錄,後續新開啓的命令行窗口須要作一樣的操做(也能夠選擇配置path路徑,一勞永逸)。
執行"mqnamesrv.cmd",看到以下圖的日誌信息表明着nameServer已經啓動成功。保持nameServer窗口開啓,不要關閉。nameServer默認的啓動端口是9876。
rocketmq 4.4.0版本的默認配置文件內存設置的比較大,若是啓動時出現了jvm內存不足之類的錯誤,能夠打開runserver.cmd對其進行編輯,將默認的jvm內存分配參數設置的小一點。
3.4 啓動broker
開啓一個新的命令行窗口,執行"mqbroker.cmd -n localhost:9876",用於啓動broker。前面提到,nameServer做爲維護路由元數據的中心,broker會在啓動時會先在nameServer進行註冊,使得生產者和消費者可以及時得到broker相關的信息。命令後面的-n localhost:9876參數就是用於指定對應nameServer的地址。
當看到以下圖所示日誌信息時,說明broker已經啓動完成。保持broker窗口開啓,不要關閉。
和nameServer啓動同樣,若是出現了內存不足的問題,能夠修改runbroker.cmd中的jvm啓動參數以符合要求。
當nameServer和broker都啓動完成後,rocketmq的服務端就已經能夠對外提供服務了。
3.5 啓動consumer和producer測試消息收發功能
rocketmq的開發人員在rocketmq中添加了簡單的demo消息收發測試程序,咱們能夠經過tools.cmd調用來進行測試(和前面同樣,其啓動時的jvm參數直接在tools.cmd中修改便可)。
首先開啓一個新的命令行窗口用於啓動consumer,先執行"set NAMESRV_ADDR=localhost:9876"設定命令行窗口級別的環境變量,而後執行"tools.cmd org.apache.rocketmq.example.quickstart.Consumer",看到以下圖所示提示信息時,表明consumer已經啓動成功。保持窗口開啓狀態,此時consumer正在監聽對應的消息,等待消費。
再開啓一個新的命令行窗口用於啓動producer,依然先執行"set NAMESRV_ADDR=localhost:9876",設定命令行窗口級別的環境變量,爲生產者指定nameServer的地址。
接着執行"tools.cmd org.apache.rocketmq.example.quickstart.Producer",如無心外,會看到發送消息的刷屏日誌,producer在一瞬間就發送了N條普通消息(1000條);
與此同時,consumer也接收到消息,並在控制檯中打印出了消息消費日誌。
至此,rocketmq的安裝與基本功能的簡單測試宣告完成。
總結
這是"rocketmq學習"系列的第一篇博客,因此先以rockemq概念的介紹和安裝入手。後續的博客內容將會有諸如rocketmq集羣部署、圖形化控制檯安裝等,並結合rocketmq的源碼進一步理解rocketmq的工做原理。
寫"rocketmq學習"系列博客的主要目的仍是爲了鞏固並加深本身對rocketmq的理解。由於對於一些知識點只有在寫做的過程當中纔會發現對其瞭解的並不透徹,經過寫博客能夠很好的查漏補缺。
若有理解不到位的地方,歡迎指正。
原文出處:https://www.cnblogs.com/xiaoxiongcanguan/p/11510366.html