RocketMQ(1)-架構原理
RocketMQ是阿里開源的分布式消息中間件,跟其它中間件相比,RocketMQ的特點是純JAVA實現;集群和HA實現相對簡單;在發生宕機和其它故障時消息丟失率更低。
一、RocketMQ專業術語
先講專業術語的含義,后面會畫流程圖來更好的去理解它們。
Producer
消息生產者,位於用戶的進程內,Producer通過NameServer獲取所有Broker的路由信息
,根據負載均衡策略選擇將消息發到哪個Broker,然后調用Broker接口提交消息。
Producer Group
生產者組,簡單來說就是多個發送同一類消息的生產者稱之為一個生產者組。
Consumer
消息消費者,位於用戶進程內。Consumer通過NameServer獲取所有broker的路由信息后,向Broker發送Pull請求來獲取消息數據。Consumer可以以兩種模式啟動,廣播(Broadcast)和集群(Cluster),廣播模式下,一條消息會發送給所有Consumer,集群模式下消息只會發送給一個Consumer。
Consumer Group
消費者組,和生產者類似,消費同一類消息的多個 Consumer 實例組成一個消費者組。
Topic
Topic用於將消息按主題做划分,Producer將消息發往指定的Topic,Consumer訂閱該Topic就可以收到這條消息。Topic跟發送方和消費方都沒有強關聯關系,發送方可以同時往多個Topic投放消息,消費方也可以訂閱多個Topic的消息。在RocketMQ中,Topic是一個上邏輯概念。消息存儲不會按Topic分開。
Message
代表一條消息,使用MessageId
唯一識別,用戶在發送時可以設置messageKey,便於之后查詢和跟蹤。一個 Message 必須指定 Topic,相當於寄信的地址。Message 還有一個可選的 Tag 設置,以便消費端可以基於 Tag 進行過濾消息。也可以添加額外的鍵值對,例如你需要一個業務 key 來查找 Broker 上的消息,方便在開發過程中診斷問題。
Tag
標簽可以被認為是對 Topic 進一步細化。一般在相同業務模塊中通過引入標簽來標記不同用途的消息。
Broker
Broker是RocketMQ的核心模塊,負責接收並存儲消息
,同時提供Push/Pull接口來將消息發送給Consumer。Consumer可選擇從Master或者Slave讀取數據。多個主/從組成Broker集群,集群內的Master節點之間不做數據交互。Broker同時提供消息查詢的功能,可以通過MessageID和MessageKey來查詢消息。Borker會將自己的Topic配置信息實時同步到NameServer。
Queue
Topic和Queue是1對多的關系,一個Topic下可以包含多個Queue,主要用於負載均衡。發送消息時,用戶只指定Topic,Producer會根據Topic的路由信息選擇具體發到哪個Queue上。Consumer訂閱消息時,會根據負載均衡策略決定訂閱哪些Queue的消息。
Offset
RocketMQ在存儲消息時會為每個Topic下的每個Queue生成一個消息的索引文件,每個Queue都對應一個Offset記錄當前Queue中消息條數。
NameServer
NameServer可以看作是RocketMQ的注冊中心,它管理兩部分數據:集群的Topic-Queue的路由配置;Broker的實時配置信息。其它模塊通過Nameserv提供的接口獲取最新的Topic配置和路由信息。
Producer/Consumer
:通過查詢接口獲取Topic對應的Broker的地址信息Broker
: 注冊配置信息到NameServer, 實時更新Topic信息到NameServer
二、流程圖
我們由簡單到復雜的來理解,它的一些核心概念
這個圖很好理解,消息先發到Topic,然后消費者去Topic拿消息。只是Topic在這里只是個概念,那它到底是怎么存儲消息數據的呢,這里就要引入Broker概念。
2、Topic的存儲
Topic是一個邏輯上的概念,實際上Message是在每個Broker上以Queue的形式記錄。
從上面的圖片可以總結下幾條結論。
1、消費者發送的Message會在Broker中的Queue隊列中記錄。
2、一個Topic的數據可能會存在多個Broker中。
3、一個Broker存在多個Queue。
4、單個的Queue也可能存儲多個Topic的消息。
也就是說每個Topic在Broker上會划分成幾個邏輯隊列,每個邏輯隊列保存一部分消息數據,但是保存的消息數據實際上不是真正的消息數據,而是指向commit log的消息索引。
Queue不是真正存儲Message的地方,真正存儲Message的地方是在CommitLog
。
如圖(盜圖)
左邊的是CommitLog。這個是真正存儲消息的地方。RocketMQ所有生產者的消息都是往這一個地方存的。
右邊是ConsumeQueue。這是一個邏輯隊列。和上文中Topic下的Queue是一一對應的。消費者是直接和ConsumeQueue打交道。ConsumeQueue記錄了消費位點,這個消費位點關聯了commitlog的位置。所以即使ConsumeQueue出問題,只要commitlog還在,消息就沒丟,可以恢復出來。還可以通過修改消費位點來重放或跳過一些消息。
3、部署模型
在部署RocketMQ時,會部署兩種角色。NameServer和Broker。如圖(盜圖)
針對這張圖做個說明
1、Product和consumer集群部署,是你開發的項目進行集群部署。
2、Broker 集群部署是為了高可用,因為Broker是真正存儲Message的地方,集群部署是為了避免一台掛掉,導致整個項目KO.
那Name SerVer是做什么用呢,它和Product、Consumer、Broker之前存在怎樣的關系呢?
先簡單概括Name Server的特點
1、Name Server是一個幾乎無狀態節點,可集群部署,節點之間無任何信息同步。
2、每個Broker與Name Server集群中的所有節點建立長連接,定時注冊Topic信息到所有Name Server。
3、Producer與Name Server集群中的其中一個節點(隨機選擇)建立長連接,定期從Name Server取Topic路由信息。
4、Consumer與Name Server集群中的其中一個節點(隨機選擇)建立長連接,定期從Name Server取Topic路由信息。
這里面最核心的是每個Broker與Name Server集群中的所有節點建立長連接
這樣做好處多多。
1、這樣可以使Name Server之間可以沒有任何關聯,因為它們綁定的Broker是一致的。
2、作為Producer或者Consumer可以綁定任何一個Name Server 因為它們都是一樣的。
三、詳解Broker
1、Broker與Name Server關系
1)連接 單個Broker和所有Name Server保持長連接。
2)心跳
心跳間隔:每隔30秒向所有NameServer發送心跳,心跳包含了自身的Topic配置信息。
心跳超時:NameServer每隔10秒,掃描所有還存活的Broker連接,若某個連接2分鍾內沒有發送心跳數據,則斷開連接。
3)斷開:當Broker掛掉;NameServer會根據心跳超時主動關閉連接,一旦連接斷開,會更新Topic與隊列的對應關系,但不會通知生產者和消費者。
2、 負載均衡
一個Topic分布在多個Broker上,一個Broker可以配置多個Topic,它們是多對多的關系。
如果某個Topic消息量很大,應該給它多配置幾個Queue,並且盡量多分布在不同Broker上,減輕某個Broker的壓力。
3 、可用性
由於消息分布在各個Broker上,一旦某個Broker宕機,則該Broker上的消息讀寫都會受到影響。
所以RocketMQ提供了Master/Slave的結構,Salve定時從Master同步數據,如果Master宕機,則Slave提供消費服務,但是不能寫入消息,此過程對應用透明,由RocketMQ內部解決。
有兩個關鍵點:
思考1
一旦某個broker master宕機,生產者和消費者多久才能發現?
受限於Rocketmq的網絡連接機制,默認情況下最多需要30秒,因為消費者每隔30秒從nameserver獲取所有topic的最新隊列情況,這意味着某個broker如果宕機,客戶端最多要30秒才能感知。
思考2
master恢復恢復后,消息能否恢復。
消費者得到Master宕機通知后,轉向Slave消費,但是Slave不能保證Master的消息100%都同步過來了,因此會有少量的消息丟失。但是消息最終不會丟的,一旦Master恢復,未同步過去的消息會被消費掉。
四 Consumer (消費者)
1 、Consumer與Name Server關系
1)連接 : 單個Consumer和一台NameServer保持長連接,如果該NameServer掛掉,消費者會自動連接下一個NameServer,直到有可用連接為止,並能自動重連。
2)心跳: 與NameServer沒有心跳
3)輪詢時間 : 默認情況下,消費者每隔30秒從NameServer獲取所有Topic的最新隊列情況,這意味着某個Broker如果宕機,客戶端最多要30秒才能感知。
2、 Consumer與Broker關系
1)連接 :單個消費者和該消費者關聯的所有broker保持長連接。
3、 負載均衡
集群消費模式下,一個消費者集群多台機器共同消費一個Topic的多個隊列,一個隊列只會被一個消費者消費。如果某個消費者掛掉,分組內其它消費者會接替掛掉的消費者繼續消費。
五、 Producer(生產者)
1、 Producer與Name Server關系
1)連接 單個Producer和一台NameServer保持長連接,如果該NameServer掛掉,生產者會自動連接下一個NameServer,直到有可用連接為止,並能自動重連。
2)輪詢時間 默認情況下,生產者每隔30秒從NameServer獲取所有Topic的最新隊列情況,這意味着某個Broker如果宕機,生產者最多要30秒才能感知,在此期間,
發往該broker的消息發送失敗。
3)心跳 與nameserver沒有心跳
2、 與broker關系
連接 單個生產者和該生產者關聯的所有broker保持長連接。
參考
2、RocketMQ nameserver、broker之間的關系
只要自己變優秀了,其他的事情才會跟着好起來(中將8)