網(wǎng)站優(yōu)化主要工作有那些內(nèi)容的磁力搜索引擎
RocketMQ 的設(shè)計(jì)理念與源碼閱讀技巧
- 一、設(shè)計(jì)理念
- 二、源碼設(shè)計(jì)
- 三、源碼閱讀技巧
一直想仔細(xì)仔細(xì)看看這個(gè) RocketMQ 的源碼,學(xué)學(xué)它的設(shè)計(jì)思想和編碼風(fēng)格,沒準(zhǔn)在以后自己在設(shè)計(jì)和編碼的時(shí)候有思考的方向。這是專欄的第一篇 —— 介紹下 RocketMQ 的一些設(shè)計(jì),懂其設(shè)計(jì)和原理,才能更好地閱讀源碼.
RocketMQ 是阿里巴巴開發(fā)的,開發(fā)之前他們也使用過(guò)當(dāng)時(shí)流行的 Kafka 作為自己的解決方案,但是是說(shuō)它沒法滿足低延遲、高可靠的要求(Kafka 若分區(qū)多了,對(duì)磁盤寫來(lái)說(shuō)會(huì)出現(xiàn)大量隨機(jī)寫的情況,寫入性能會(huì)下降很多,這里說(shuō)的低延遲與實(shí)際使用方式和數(shù)據(jù)存儲(chǔ)實(shí)現(xiàn)有關(guān)系),當(dāng)然還有其它原因,所以它們決定開發(fā)一款新的消息傳遞引擎來(lái)滿足自己的業(yè)務(wù)需求。
上面內(nèi)容來(lái)自:RocketMQ 官方文檔
一、設(shè)計(jì)理念
咱先聊聊設(shè)計(jì)一款消息中間件需要具備的要素,設(shè)計(jì)一款消息隊(duì)列中間件,首先它需要對(duì)外提供通信路口,提供生產(chǎn)、消費(fèi)消息的路口,即需要具備網(wǎng)絡(luò)通信能力;其次就是它得具備數(shù)據(jù)存儲(chǔ)的能力,這數(shù)據(jù)包含消息本身與元數(shù)據(jù)存儲(chǔ)。
了解完設(shè)計(jì)消息隊(duì)列的必要元素,咱來(lái)看看 RocketMQ 的技術(shù)架構(gòu):
主要由四部分組成:
- NameServer
- 被用來(lái)當(dāng)做信息管理的"注冊(cè)中心",主要是用來(lái)管理元數(shù)據(jù)(路由信息)。Kafka 元數(shù)據(jù)管理是用的 Zookeeper,而 RocketMQ 是自己寫了一個(gè)服務(wù)實(shí)現(xiàn)這個(gè)元數(shù)據(jù)注冊(cè)中心,寫的這個(gè)服務(wù)被稱為 NameServer,NameServer 被設(shè)計(jì)出來(lái)是一種無(wú)狀態(tài)的,即 NameServer 集群之間是不通信的,這樣做一方面可以滿足實(shí)際需求的前提下(路由信息無(wú)需保障集群之間強(qiáng)一致性,可以容忍分鐘級(jí)別的不一致),相比 Zookeeper 性能也有極大的提升。
- Broker
- 主要用來(lái)做消息存儲(chǔ)的服務(wù)
- Producer、Consumer
- 消息隊(duì)列的客戶端,除了實(shí)現(xiàn)消息的發(fā)送消費(fèi)外,RocketMQ 很多功能交給了客戶端進(jìn)行實(shí)現(xiàn),減輕消息中間件的實(shí)現(xiàn)復(fù)雜度,像消息生產(chǎn)的高可用、消息順序消費(fèi)、消費(fèi)冪等等等,這些功能都是交由客戶端實(shí)現(xiàn)的。
二、源碼設(shè)計(jì)
看源碼第一步就是下載源碼:https://github.com/apache/rocketmq
隨后了解一下源碼的目錄結(jié)構(gòu):
RocketMQ核心目錄說(shuō)明如下:
- acl:權(quán)限控制模塊
- broker:broker模塊(broker啟動(dòng)進(jìn)程)
- client:消息客戶端,包含消息生產(chǎn)者和消息消費(fèi)者相關(guān)類
- common:公共包
- dev:開發(fā)者信息(非源碼)
- distribution:打包分發(fā)目錄(非源碼)
- example:RocketMQ示例代碼
- filter:消息過(guò)濾相關(guān)基礎(chǔ)類
- logappender:日志實(shí)現(xiàn)相關(guān)類
- logging:自主實(shí)現(xiàn)日志相關(guān)類
- namesrv:NameServer實(shí)現(xiàn)相關(guān)類(NameServer啟動(dòng)進(jìn)程)
- openmessaging:消息開放標(biāo)準(zhǔn),已發(fā)布
- remoting:遠(yuǎn)程通信模塊,基于Netty
- srvutil:服務(wù)器工具類
- store:消息存儲(chǔ)實(shí)現(xiàn)相關(guān)類
- style:checkstyle相關(guān)實(shí)現(xiàn)
- test:測(cè)試相關(guān)類
- tools:工具類,監(jiān)控命令相關(guān)實(shí)現(xiàn)類
RocketMQ 的網(wǎng)絡(luò)通信是基于 Netty 實(shí)現(xiàn)的,這里需要提一下它是如何設(shè)計(jì)接收網(wǎng)絡(luò)消息去執(zhí)行任務(wù)的,如何進(jìn)行的編碼設(shè)計(jì)使得它更具拓展,更靈活。
其實(shí)在服務(wù)端(NameServer、Broker)/客戶端(Producer、Consumer)中都維護(hù)了一個(gè) processorTable,是一個(gè) k-v 集合,key 是服務(wù)碼 requestCode,value 是對(duì)應(yīng)的執(zhí)行單元 Pair<NettryRequestProcessor, ExecutorService> 類型,包含了處理 Processor 和執(zhí)行線程的線程池。里面對(duì)應(yīng)內(nèi)容在對(duì)應(yīng)業(yè)務(wù)系統(tǒng)啟動(dòng)的時(shí)候會(huì)自行注冊(cè)。
客戶端發(fā)送網(wǎng)絡(luò)包的時(shí)候會(huì)攜帶 RequestCode,服務(wù)端接收網(wǎng)絡(luò)包后進(jìn)行解碼得到 RequestCode,然后通過(guò) ProcessorTable 找對(duì)應(yīng) Processor 任務(wù)拿對(duì)應(yīng)線程池進(jìn)行執(zhí)行,從而實(shí)現(xiàn)了異步任務(wù)執(zhí)行。這種服務(wù)注冊(cè)機(jī)制,簡(jiǎn)潔且靈活。
類似這種使用 Netty 實(shí)現(xiàn)通信然后與業(yè)務(wù)結(jié)合的編碼設(shè)計(jì),我在 IM 系統(tǒng)、貨柜系統(tǒng)也看見過(guò)。
三、源碼閱讀技巧
- 先理解相應(yīng)底層原理,再去針對(duì)性的看源碼實(shí)現(xiàn),學(xué)習(xí)編碼,驗(yàn)證原理
- 源碼閱讀建議起始點(diǎn)
- Broker 啟動(dòng):BrokerStartup#start、NameServer 啟動(dòng):NamesrvStartup#start、客戶端相關(guān)的源碼閱讀可以從 example 目錄下的用例直接入手
- 不太建議 Debug 閱讀源碼,建議靜態(tài)看源碼,看不懂的地方再嘗試調(diào)試跟進(jìn)。一方面是對(duì)這種能力的培養(yǎng),另一方面中間件源碼不同于業(yè)務(wù)系統(tǒng),中間件源碼堆棧太多,容易繞暈,而且很多異步
- 書籍與博客輔助看源碼
- 書籍推薦:《RocketMQ 技術(shù)內(nèi)幕》
- 反復(fù)看