Rocketmq源碼分析01:搭建源碼調(diào)試環(huán)境

Rocketmq源碼分析01:搭建源碼調(diào)試環(huán)境

轉(zhuǎn)載地址:https://mp.weixin.qq.com/s/waDzMr4rOaC_NlxSqF0YCg

1. 基本架構(gòu)

RocketMQ架構(gòu)上主要分為四部分搏嗡,如下圖所示:

圖片
  • Producer:消息發(fā)布的角色惜姐,支持分布式集群方式部署较木。Producer通過MQ的負(fù)載均衡模塊選擇相應(yīng)的Broker集群隊(duì)列進(jìn)行消息投遞武翎,投遞的過程支持快速失敗并且低延遲饺藤。

  • Consumer:消息消費(fèi)的角色,支持分布式集群方式部署诊沪。支持以push推被啼,pull拉兩種模式對(duì)消息進(jìn)行消費(fèi)。同時(shí)也支持集群方式和廣播方式的消費(fèi)猪勇,它提供實(shí)時(shí)消息訂閱機(jī)制设褐,可以滿足大多數(shù)用戶的需求。

  • NameServerNameServer是一個(gè)非常簡單的Topic路由注冊(cè)中心泣刹,其角色類似Dubbo中的zookeeper助析,支持Broker的動(dòng)態(tài)注冊(cè)與發(fā)現(xiàn)。主要包括兩個(gè)功能:

    NameServer通常也是集群的方式部署椅您,各實(shí)例間相互不進(jìn)行信息通訊外冀。Broker是向每一臺(tái)NameServer注冊(cè)自己的路由信息,所以每一個(gè)NameServer實(shí)例上面都保存一份完整的路由信息掀泳。當(dāng)某個(gè)NameServer因某種原因下線了雪隧,Broker仍然可以向其它NameServer同步其路由信息,Producer,Consumer仍然可以動(dòng)態(tài)感知Broker的路由的信息开伏。

    • Broker管理膀跌,NameServer接受Broker集群的注冊(cè)信息并且保存下來作為路由信息的基本數(shù)據(jù)遭商。然后提供心跳檢測機(jī)制固灵,檢查Broker是否還存活;
    • 路由信息管理劫流,每個(gè)NameServer將保存關(guān)于Broker集群的整個(gè)路由信息和用于客戶端查詢的隊(duì)列信息巫玻。然后ProducerConumser通過NameServer就可以知道整個(gè)Broker集群的路由信息丛忆,從而進(jìn)行消息的投遞和消費(fèi)。
  • BrokerServerBroker主要負(fù)責(zé)消息的存儲(chǔ)仍秤、投遞和查詢以及服務(wù)高可用保證熄诡,為了實(shí)現(xiàn)這些功能,Broker包含了以下幾個(gè)重要子模塊:

    • Client Manager:負(fù)責(zé)管理客戶端(Producer/Consumer)和維護(hù)ConsumerTopic訂閱信息
    • Store Service:提供方便簡單的API接口處理消息存儲(chǔ)到物理硬盤和查詢功能诗力。
    • HA Service:高可用服務(wù)凰浮,提供Master BrokerSlave Broker之間的數(shù)據(jù)同步功能。
    • Index Service:根據(jù)特定的Message key對(duì)投遞到Broker的消息進(jìn)行索引服務(wù)苇本,以提供消息的快速查詢袜茧。
    • Remoting Module:整個(gè)Broker的實(shí)體,負(fù)責(zé)處理來自clients端的請(qǐng)求瓣窄。
圖片

2. 獲取源碼

rocketMq項(xiàng)目的github倉庫為https://github.com/apache/rocketmq.git笛厦,由于網(wǎng)絡(luò)原因,我們并不會(huì)直接使用github倉庫俺夕,而是將其導(dǎo)入到gitee上裳凸,只需在gitee創(chuàng)建新倉庫時(shí),選擇導(dǎo)入已有倉庫即可:

圖片

導(dǎo)入到gitee后劝贸,就可以進(jìn)行checkout了姨谷,本文對(duì)應(yīng)的gitee倉庫為https://gitee.com/funcy/rocketmq.git

checkout源碼到本地后映九,默認(rèn)是master分支菠秒,本人習(xí)慣基于tag創(chuàng)建自己的分支,然后在自己的分支上進(jìn)行分析氯迂,rocketMqtag如下:

圖片

最新版本是4.8.0践叠,我們將基于此tag創(chuàng)建新分支,使用的命令如下:

# 切換到 rocketmq-all-4.8.0
git checkout rocketmq-all-4.8.0
# 基于 rocketmq-all-4.8.0 創(chuàng)建自己的分析嚼蚀,名稱為 rocketmq-all-4.8.0-LEARN
git checkout -b rocketmq-all-4.8.0-LEARN
# 將 rocketmq-all-4.8.0-LEARN 分支推送到遠(yuǎn)程倉庫
git push -u origin rocketmq-all-4.8.0-LEARN

接下來禁灼,我們所有的操作都是在rocketmq-all-4.8.0-LEARN分支上進(jìn)行了。

3. 本地啟動(dòng)

拿到代碼后轿曙,我們就開始進(jìn)行本地啟動(dòng)了弄捕,沒錯(cuò),就是在idea中進(jìn)行啟動(dòng)导帝。

3.1 復(fù)制conf目錄

在啟動(dòng)項(xiàng)目前守谓,我們需要進(jìn)行一些配置,rocketMq項(xiàng)目的配置文件位于rocketmq/distribution模塊下的conf目錄中您单,直接整個(gè)復(fù)制到rocketmq目錄下:

圖片

也不需要改動(dòng)斋荞,復(fù)制出來就行了,這些配置的內(nèi)容后面分析源碼時(shí)再講解吧虐秦。

3.2 啟動(dòng)nameServer

nameServer的主類為org.apache.rocketmq.namesrv.NamesrvStartup

圖片

如果我們直接運(yùn)行main()方法平酿,會(huì)報(bào)錯(cuò):

圖片

報(bào)錯(cuò)信息已經(jīng)很明確了凤优,需要我們配置ROCKETMQ_HOME目錄,我們?cè)?code>idea中進(jìn)行配置即可:

打開配置界面:

圖片

填寫ROCKETMQ_HOME配置:

圖片

這里我填寫的是ROCKETMQ_HOME=/Users/chengyan/IdeaProjects/myproject/rocketmq蜈彼,這個(gè)ROCKETMQ_HOME路徑就是conf文件夾所在的目錄筑辨。

填寫好后,就可以啟動(dòng)了:

圖片

3.3 啟動(dòng)broker

broker的主類為org.apache.rocketmq.broker.BrokerStartup幸逆,啟動(dòng)方式與nameServer很相似棍辕,啟動(dòng)前也要配置ROCKETMQ_HOME路徑:

圖片

Idea 老版本配置


image.png

相比于nameServer,這里多配置了啟動(dòng)參數(shù):

-n localhost:9876 autoCreateTopicEnable=true

這個(gè)啟動(dòng)參數(shù)是指定nameServer的地址还绘,以及開啟自動(dòng)創(chuàng)建topic的功能痢毒。

配置完成之后就可以啟動(dòng)了:

圖片

3.4 啟動(dòng)管理后臺(tái)

rocketMq的管理后臺(tái)在另一個(gè)倉庫https://github.com/apache/rocketmq-externals,除了后臺(tái)蚕甥,這個(gè)倉庫還包含了許多的其他模塊:

圖片

我們并不需要分析這個(gè)項(xiàng)目哪替,源碼本可以不必下載,但我在找這個(gè)項(xiàng)目的release版本時(shí)菇怀,發(fā)現(xiàn)并沒有提供已編譯好的jar包凭舶,需要自己構(gòu)建代碼,因此我就再次下載了這個(gè)代碼源碼爱沟。當(dāng)然帅霜,由于網(wǎng)絡(luò)的原因,這個(gè)項(xiàng)目的源碼也被我導(dǎo)入到了gitee上呼伸,地址為https://gitee.com/funcy/rocketmq-externals.git.

這個(gè)項(xiàng)目的代碼我們并不分析身冀,因此直接在master分支上操作即可,

管理后臺(tái)項(xiàng)目為rocketmq-console括享,主類為org.apache.rocketmq.console.App

圖片

在啟動(dòng)前搂根,我們需要修改下application.properties的配置,找到rocketmq.config.namesrvAddr配置铃辖,添加nameServer的ip與端口剩愧,這里我們連接的是本地應(yīng)用,直接填寫localhost:9876

...
rocketmq.config.namesrvAddr=localhost:9876
...

啟動(dòng)娇斩,結(jié)果如下:

圖片

訪問http://localhost:8080仁卷,結(jié)果如下:

圖片

可以看到broker已經(jīng)出現(xiàn)在cluster列表中了,這就表明啟動(dòng)成功了犬第。

4. 收發(fā)消息測試

rocketMq項(xiàng)目的example模塊下有大量的測試示例锦积,我們選擇其一進(jìn)行消息收發(fā)測試。

4.1 啟動(dòng)Consumer

我們先找到org.apache.rocketmq.example.simple.PushConsumer歉嗓,代碼如下:

public class PushConsumer {

    public static void main(String[] args) 
            throws InterruptedException, MQClientException {
        String nameServer = "localhost:9876";
        DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("CID_JODIE_1");
        consumer.setNamesrvAddr(nameServer);
        consumer.subscribe("TopicTest", "*");
        consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);
        //wrong time format 2017_0422_221800
        consumer.setConsumeTimestamp("20181109221800");
        consumer.registerMessageListener(new MessageListenerConcurrently() {

            @Override
            public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, 
                    ConsumeConcurrentlyContext context) {
                System.out.printf("%s Receive New Messages: %s %n", 
                    Thread.currentThread().getName(), msgs);
                return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
            }
        });
        consumer.start();
        System.out.printf("Consumer Started.%n");
    }
}

這個(gè)Consumer監(jiān)聽的topicTopicTest丰介,后面我們就會(huì)往這個(gè)topic發(fā)送消息。另外,需要注意nameServer的配置基矮,我們是在本地啟動(dòng)的nameServer,因此這里配置的是localhost:9876冠场。

運(yùn)行main()方法家浇,結(jié)果如下:

圖片

4.2 啟動(dòng)Producer

我們找到 org.apache.rocketmq.example.simple.Producer 類,代碼如下:

public class Producer {

    public static void main(String[] args) 
            throws MQClientException, InterruptedException {
        String nameServer = "localhost:9876";
        DefaultMQProducer producer = new DefaultMQProducer("ProducerGroupName");
        producer.setNamesrvAddr(nameServer);
        producer.start();

        for (int i = 0; i < 10; i++)
            try {
                {
                    Message msg = new Message("TopicTest",
                        "TagA",
                        "OrderID188",
                        "Hello world".getBytes(RemotingHelper.DEFAULT_CHARSET));
                    SendResult sendResult = producer.send(msg);
                    System.out.printf("%s%n", sendResult);
                }

            } catch (Exception e) {
                e.printStackTrace();
            }

        producer.shutdown();
    }
}

同樣地碴裙,這里使用的是的nameServer地址是localhost:9876钢悲,topicTopicTest,運(yùn)行舔株,結(jié)果如下:

圖片

再回過頭看看PushConsumer的控制臺(tái):

圖片

可以看到莺琳,Producer發(fā)送消息成功了,PushConsumer也成功獲取到消息了载慈。

4.3 異常分析

如圖所示:

圖片

如果出現(xiàn)異常:

org.apache.rocketmq.client.exception.MQClientException: 
No route info of this topic: TopicTest

這表明當(dāng)前broker中沒有TopicTesttopic惭等,這時(shí)我們可以手動(dòng)創(chuàng)建topic,也可以在啟動(dòng)時(shí)指定autoCreateTopicEnable=true.

如果是按上面步驟進(jìn)行的办铡,請(qǐng)確認(rèn)下org.apache.rocketmq.broker.BrokerStartup是否配置啟動(dòng)參數(shù)

-n localhost:9876 autoCreateTopicEnable=true

配置方式就按3.3節(jié)的方式配置就行了辞做。

5. 總結(jié)

本文主要介紹了rocketMq的基本架構(gòu),通過源碼展示了rocketMq的啟動(dòng)方式寡具,最后通過rocketMq項(xiàng)目下example模塊中的測試代碼展示了消息的收發(fā)過程秤茅。

總的來說,本文還是在準(zhǔn)備源碼分析的環(huán)境童叠,下篇文章開始框喳,我們就正式開始rocketMq的源碼分析了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末厦坛,一起剝皮案震驚了整個(gè)濱河市五垮,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌杜秸,老刑警劉巖拼余,帶你破解...
    沈念sama閱讀 222,183評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異亩歹,居然都是意外死亡匙监,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門小作,熙熙樓的掌柜王于貴愁眉苦臉地迎上來亭姥,“玉大人,你說我怎么就攤上這事顾稀〈锫蓿” “怎么了?”我有些...
    開封第一講書人閱讀 168,766評(píng)論 0 361
  • 文/不壞的土叔 我叫張陵,是天一觀的道長粮揉。 經(jīng)常有香客問我巡李,道長,這世上最難降的妖魔是什么扶认? 我笑而不...
    開封第一講書人閱讀 59,854評(píng)論 1 299
  • 正文 為了忘掉前任侨拦,我火速辦了婚禮,結(jié)果婚禮上辐宾,老公的妹妹穿的比我還像新娘狱从。我一直安慰自己,他們只是感情好叠纹,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,871評(píng)論 6 398
  • 文/花漫 我一把揭開白布季研。 她就那樣靜靜地躺著,像睡著了一般誉察。 火紅的嫁衣襯著肌膚如雪与涡。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,457評(píng)論 1 311
  • 那天持偏,我揣著相機(jī)與錄音递沪,去河邊找鬼。 笑死综液,一個(gè)胖子當(dāng)著我的面吹牛款慨,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播谬莹,決...
    沈念sama閱讀 40,999評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼檩奠,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了附帽?” 一聲冷哼從身側(cè)響起埠戳,我...
    開封第一講書人閱讀 39,914評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎蕉扮,沒想到半個(gè)月后整胃,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,465評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡喳钟,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,543評(píng)論 3 342
  • 正文 我和宋清朗相戀三年屁使,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片奔则。...
    茶點(diǎn)故事閱讀 40,675評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡蛮寂,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出易茬,到底是詐尸還是另有隱情酬蹋,我是刑警寧澤,帶...
    沈念sama閱讀 36,354評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站范抓,受9級(jí)特大地震影響骄恶,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜匕垫,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,029評(píng)論 3 335
  • 文/蒙蒙 一僧鲁、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧年缎,春花似錦悔捶、人聲如沸铃慷。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽犁柜。三九已至洲鸠,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間馋缅,已是汗流浹背扒腕。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評(píng)論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留萤悴,地道東北人瘾腰。 一個(gè)月前我還...
    沈念sama閱讀 49,091評(píng)論 3 378
  • 正文 我出身青樓,卻偏偏與公主長得像覆履,于是被迫代替她去往敵國和親蹋盆。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,685評(píng)論 2 360