仿照Kafka崎脉,從零開始自實現(xiàn) MQ

仿照Kafka,從零開始自實現(xiàn) MQ伯顶,實現(xiàn)了 Kafka 中 80% 的基礎(chǔ)功能囚灼。學(xué)習(xí) Kafka 的話如果只是看文章和源碼,可能不久就會忘了祭衩,還是自己實現(xiàn)一個「精簡版」的 Kafka 吧灶体,

實現(xiàn)功能概覽

1、基于內(nèi)存Queue實現(xiàn)生產(chǎn)和消費(fèi)API

  • 1) 創(chuàng)建內(nèi)存Queue掐暮, 作為底層消息存儲
  • 2) 定義Topic蝎抽, 支持多個Topic
  • 3) 定義Producer, 支持Send消息
  • 4) 定義Consumer路克, 支持Poll消息

2樟结、設(shè)計自定義Queue,實現(xiàn)消息確認(rèn)和消費(fèi)offset

  • 1) 自定義內(nèi)存Message數(shù)組模擬Queue精算。
  • 2) 使用指針記錄當(dāng)前消息寫入位置瓢宦。
  • 3) 對于每個命名消費(fèi)者, 用指針記錄消費(fèi)位置

3灰羽、拆分broker和client(包括producer和consumer)

  • 1) 將Queue保存到web server端
  • 2) 設(shè)計消息讀寫API接口驮履, 確認(rèn)接口, 提交offset接口
  • 3) producer和consumer通過httpclient訪問Queue
  • 4) 實現(xiàn)消息確認(rèn)谦趣, offset提交
  • 5) 實現(xiàn)consumer從offset增量拉取

項目目錄

bitkylin-mq

項目設(shè)計及項目能力

Server

一疲吸、Topic

  1. 維護(hù)ArrayList用于模擬持久化消息「原因:消息需要隨機(jī)訪問」
  2. 設(shè)定消息隊列容量,達(dá)到容量時無法再生產(chǎn)消息
  3. 當(dāng)前消息的最大索引

二前鹅、ConsumerGroup

  1. 消費(fèi)者組由消費(fèi)者組名和topic名共同決定摘悴,即不同topic的消費(fèi)者組相互獨立,不會相互影響
  2. 需根據(jù)topic創(chuàng)建消費(fèi)者組舰绘,即消費(fèi)者組必須關(guān)聯(lián)topic
  3. 消費(fèi)者組創(chuàng)建后蹂喻,默認(rèn)從頭完整消費(fèi)關(guān)聯(lián)topic的所有消息
  4. 同一個消費(fèi)者組內(nèi)葱椭,各個消費(fèi)者總共消費(fèi)一次「最少消費(fèi)一次」所關(guān)聯(lián)topic的所有消息

三、broker

  1. 一個broker關(guān)聯(lián)一個ConsumerGroup列表和一個Topic列表
  2. 通過broker暴露的接口口四,可以展示關(guān)聯(lián)ConsumerGroup列表和Topic列表的概覽信息
  3. 通過broker暴露的接口孵运,可以向一個topic中生產(chǎn)消息
  4. 通過broker暴露的接口,可以根據(jù)消費(fèi)者組名和topic名消費(fèi)消息

注:本次僅實現(xiàn)單個broker蔓彩,broker后實現(xiàn)了topic和consumerGroup「消費(fèi)者組」治笨,細(xì)節(jié)結(jié)構(gòu)圖如下:

mq-broker

client

  1. 客戶端通過topic名生產(chǎn)消息
  2. 客戶端根據(jù)消費(fèi)者組名和topic名消費(fèi)消息
  3. 客戶端消費(fèi)消息時,可以同時獲得消費(fèi)者組的offset「偏移量」
  4. 客戶端消費(fèi)消息成功后赤嚼,需手動更新消費(fèi)者組的offset旷赖。若不更新,客戶端默認(rèn)無法消費(fèi)后面的消息更卒。
  5. 客戶端消費(fèi)消息失敗時等孵,不應(yīng)更新消費(fèi)者組的offset。此時客戶端可以重復(fù)消費(fèi)當(dāng)條消息蹂空。
  6. 多個客戶端可以使用同一個消費(fèi)者組消費(fèi)同一個topic俯萌;可以使用不同的消費(fèi)者組消費(fèi)同一個topic;可以使用不同的消費(fèi)者組消費(fèi)不同的topic

客戶端工作示意圖如下:

message-producer-consumer

項目結(jié)構(gòu)

本項目共提供四個module:

bitkylin-mq-server
bitkylin-mq-api
bitkylin-mq-client-producer
bitkylin-mq-client-consumer

各module的介紹如下:

1. bitkylin-mq-server

提供MQ服務(wù)端上枕,提供broker以及其關(guān)聯(lián)的ConsumerGroup和Topic等咐熙,主要實現(xiàn)如下功能:

  • 展示MQ概覽信息,包括topic和ConsumerGroup的詳細(xì)信息
  • 創(chuàng)建消費(fèi)者組辨萍,創(chuàng)建消費(fèi)者組后糖声,即可使用該消費(fèi)者組消費(fèi)消息
  • 生產(chǎn)消息,將消息發(fā)送至指定topic
  • 基于指定消費(fèi)者組消費(fèi)消息分瘦,消費(fèi)消息但不更新關(guān)聯(lián)消費(fèi)者組的offset
  • 基于指定消費(fèi)者組消費(fèi)消息蘸泻,消費(fèi)消息且自動更新關(guān)聯(lián)消費(fèi)者組的offset
  • 手動更新指定消費(fèi)者組的偏移量

2. bitkylin-mq-api

提供供客戶端使用的api,通過feignClient形式提供嘲玫,客戶端可直接使用悦施,執(zhí)行RPC,當(dāng)前實現(xiàn)如下功能:

  • 發(fā)送消息至指定topic
  • 訂閱指定topic的消息去团。自動創(chuàng)建消費(fèi)者組抡诞,使用觀察者模式輪詢消息并消費(fèi)。

3. bitkylin-mq-client-producer

消息生產(chǎn)客戶端土陪,通過feign-api生產(chǎn)消息昼汗,當(dāng)前實現(xiàn)如下演示功能:
隨機(jī)向topic名為「topic-1」和「topic-2」的topic中發(fā)送消息,每隔3秒發(fā)送一次消息鬼雀。

4. bitkylin-mq-client-consumer

消息消費(fèi)客戶端顷窒,通過feign-api消費(fèi)消息,當(dāng)前實現(xiàn)如下演示功能:

  • 創(chuàng)建消費(fèi)者組「spring-group-1」訂閱「topic-1」,并打印訂閱的消息鞋吉。
  • 創(chuàng)建消費(fèi)者組「spring-group-2」訂閱「topic-2」鸦做,并打印訂閱的消息。

代碼演示

  1. 運(yùn)行module「bitkylin-mq-server」谓着,啟動MQ的broker泼诱,啟動消息服務(wù)。
  2. 運(yùn)行module「bitkylin-mq-client-consumer」和「bitkylin-mq-client-producer」赊锚,開啟消息訂閱演示任務(wù)和消息發(fā)送演示任務(wù)治筒。
  3. 此時可通過「bitkylin-mq-client-consumer」的控制臺,看到消息不斷被消費(fèi)舷蒲。
2021-01-24 01:55:58.008  INFO 2516 --- [pool-1-thread-1] .c.c.BitkylinMqClientConsumerApplication : 收到消息:spring-group-1: topic-1-msg:1
2021-01-24 01:56:00.996  INFO 2516 --- [pool-1-thread-1] .c.c.BitkylinMqClientConsumerApplication : 收到消息:spring-group-1: topic-1-msg:2
2021-01-24 01:56:04.000  INFO 2516 --- [pool-1-thread-1] .c.c.BitkylinMqClientConsumerApplication : 收到消息:spring-group-1: topic-1-msg:3
2021-01-24 01:56:07.004  INFO 2516 --- [pool-2-thread-1] .c.c.BitkylinMqClientConsumerApplication : 收到消息:spring-group-2: topic-2-msg:4
2021-01-24 01:56:10.015  INFO 2516 --- [pool-2-thread-1] .c.c.BitkylinMqClientConsumerApplication : 收到消息:spring-group-2: topic-2-msg:5
2021-01-24 01:56:13.011  INFO 2516 --- [pool-2-thread-1] .c.c.BitkylinMqClientConsumerApplication : 收到消息:spring-group-2: topic-2-msg:6
2021-01-24 01:56:16.011  INFO 2516 --- [pool-2-thread-1] .c.c.BitkylinMqClientConsumerApplication : 收到消息:spring-group-2: topic-2-msg:7
2021-01-24 01:56:19.006  INFO 2516 --- [pool-2-thread-1] .c.c.BitkylinMqClientConsumerApplication : 收到消息:spring-group-2: topic-2-msg:8
2021-01-24 01:56:21.997  INFO 2516 --- [pool-1-thread-1] .c.c.BitkylinMqClientConsumerApplication : 收到消息:spring-group-1: topic-1-msg:9
2021-01-24 01:56:24.994  INFO 2516 --- [pool-1-thread-1] .c.c.BitkylinMqClientConsumerApplication : 收到消息:spring-group-1: topic-1-msg:10
2021-01-24 01:56:28.002  INFO 2516 --- [pool-2-thread-1] .c.c.BitkylinMqClientConsumerApplication : 收到消息:spring-group-2: topic-2-msg:11
2021-01-24 01:56:30.991  INFO 2516 --- [pool-1-thread-1] .c.c.BitkylinMqClientConsumerApplication : 收到消息:spring-group-1: topic-1-msg:12
2021-01-24 01:56:34.014  INFO 2516 --- [pool-2-thread-1] .c.c.BitkylinMqClientConsumerApplication : 收到消息:spring-group-2: topic-2-msg:13
2021-01-24 01:56:37.010  INFO 2516 --- [pool-2-thread-1] .c.c.BitkylinMqClientConsumerApplication : 收到消息:spring-group-2: topic-2-msg:14
2021-01-24 01:56:40.004  INFO 2516 --- [pool-2-thread-1] .c.c.BitkylinMqClientConsumerApplication : 收到消息:spring-group-2: topic-2-msg:15
  1. 打開postman矢炼,發(fā)送如下請求創(chuàng)建專用于postman的消費(fèi)者組:
POST http://localhost:8080/mq/broker/consumer-group/create

{
    "groupName": "postman-group-1",
    "topicName": "topic-1"
}
  1. 發(fā)送如下請求即可消費(fèi)消息,且自動確認(rèn)「無需手動更新消費(fèi)者組的offset」
POST http://localhost:8080/mq/broker/message/simple-pull

{
    "groupName": "postman-group-1",
    "topicName": "topic-1"
}

可以發(fā)現(xiàn)阿纤,postman可以獨立消費(fèi)指定topic的消息,不受Spring程序消費(fèi)的影響夷陋。當(dāng)然欠拾,postman可以直接使用Spring程序一致的消費(fèi)者組,以共同消費(fèi)消息骗绕。

此時查詢MQ的概覽信息:

GET http://localhost:8080/mq/broker/overview

響應(yīng):

{
  "groupList": [
    {
      "groupName": "spring-group-1",
      "topic": {
        "name": "topic-1",
        "capacity": 1000,
        "maxIndex": 14
      },
      "offset": 15
    },
    {
      "groupName": "postman-group-1",
      "topic": {
        "name": "topic-1",
        "capacity": 1000,
        "maxIndex": 14
      },
      "offset": 5
    },
    {
      "groupName": "spring-group-2",
      "topic": {
        "name": "topic-2",
        "capacity": 1000,
        "maxIndex": 17
      },
      "offset": 18
    }
  ]
}

局限性

  1. 每個topic的隊列容量是固定的藐窄,隊列滿后拒絕生產(chǎn)消息,暫不支持清理歷史消息酬土。
  2. 消息消費(fèi)未加鎖荆忍,如果一個消費(fèi)者組的多個消費(fèi)者高并發(fā)消費(fèi)消息,可能導(dǎo)致同一條消息被消費(fèi)多次撤缴。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末刹枉,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子屈呕,更是在濱河造成了極大的恐慌微宝,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,000評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件虎眨,死亡現(xiàn)場離奇詭異蟋软,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)嗽桩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,745評論 3 399
  • 文/潘曉璐 我一進(jìn)店門岳守,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人碌冶,你說我怎么就攤上這事湿痢。” “怎么了扑庞?”我有些...
    開封第一講書人閱讀 168,561評論 0 360
  • 文/不壞的土叔 我叫張陵蒙袍,是天一觀的道長俊卤。 經(jīng)常有香客問我,道長害幅,這世上最難降的妖魔是什么消恍? 我笑而不...
    開封第一講書人閱讀 59,782評論 1 298
  • 正文 為了忘掉前任,我火速辦了婚禮以现,結(jié)果婚禮上狠怨,老公的妹妹穿的比我還像新娘。我一直安慰自己邑遏,他們只是感情好佣赖,可當(dāng)我...
    茶點故事閱讀 68,798評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著记盒,像睡著了一般憎蛤。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上纪吮,一...
    開封第一講書人閱讀 52,394評論 1 310
  • 那天俩檬,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛槽卫,可吹牛的內(nèi)容都是我干的咕娄。 我是一名探鬼主播,決...
    沈念sama閱讀 40,952評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起联逻,我...
    開封第一講書人閱讀 39,852評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎检痰,沒想到半個月后遣妥,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,409評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡攀细,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,483評論 3 341
  • 正文 我和宋清朗相戀三年箫踩,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片谭贪。...
    茶點故事閱讀 40,615評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡境钟,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出俭识,到底是詐尸還是另有隱情慨削,我是刑警寧澤,帶...
    沈念sama閱讀 36,303評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站缚态,受9級特大地震影響磁椒,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜玫芦,卻給世界環(huán)境...
    茶點故事閱讀 41,979評論 3 334
  • 文/蒙蒙 一浆熔、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧桥帆,春花似錦医增、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,470評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至祈匙,卻和暖如春忽刽,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背夺欲。 一陣腳步聲響...
    開封第一講書人閱讀 33,571評論 1 272
  • 我被黑心中介騙來泰國打工跪帝, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人洁闰。 一個月前我還...
    沈念sama閱讀 49,041評論 3 377
  • 正文 我出身青樓,卻偏偏與公主長得像万细,于是被迫代替她去往敵國和親扑眉。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,630評論 2 359

推薦閱讀更多精彩內(nèi)容