概述
? ? 這篇文章是以同事在實際工作中遇到的問題作為分析的切入點惶室,加深自己對mq的掌握,踐行“干中學(xué)”的團(tuán)隊理念。
? ? 當(dāng)自己差不多把基本概念都掌握的差不多的時候啊终,必須需要實際的案例或者實踐來提深自己的深度疑苔,這個時候just do it 變得很重要甫匹,所以我喜歡不停的被人挑戰(zhàn),截止目前幫人解答的問題包括:client端消息堆積問題惦费、批量消息拉取問題中遇到的神奇的數(shù)字32兵迅、以及本篇的tag不一致造成的假象,也就說會有3篇文章輸出趁餐。
? ? 整個mq的問題解決文章會收錄在mq的另外一個《rocketMq干中學(xué)》專題當(dāng)中喷兼,歡迎訂閱,歡迎挑戰(zhàn)后雷。
背景
????某次線上發(fā)布升級mq的消費(fèi)端修改訂閱的topic對應(yīng)的tags季惯,為了保證穩(wěn)定性,采取了灰度發(fā)布策略臀突,也就說發(fā)布一臺服務(wù)后觀察一段時間看是否正常再全量發(fā)布勉抓。
? ? 升級的內(nèi)容為consumer訂閱的tags信息,灰度一臺之后存在同一個consumeGroup下有多個consumer候学,且其中一個consumer的topic的tags信息和其他consumer不一致藕筋。
? ? 如我們在consumeGroupA下有3個consumer,一開始3個consumer訂閱了topicA + tagA||tagB梳码,然后我們升級一個consumer訂閱topicA+tagC隐圾,這個時候在同一個consumeGroup下針對同一個topic會有兩個不同的訂閱信息。
? ? 升級以后的現(xiàn)象是什么呢掰茶,重要的事情說3遍暇藏,說3遍,說3遍濒蒋。
? ? 升級后我們發(fā)現(xiàn)所有的consumer都沒有消費(fèi)數(shù)據(jù)的記錄盐碱!
?????升級后我們發(fā)現(xiàn)所有的consumer都沒有消費(fèi)數(shù)據(jù)的記錄!?
????升級后我們發(fā)現(xiàn)所有的consumer都沒有消費(fèi)數(shù)據(jù)的記錄沪伙!
復(fù)現(xiàn)
????請按照以下順序進(jìn)行復(fù)現(xiàn)操作
????????1瓮顽、啟動consumeA,負(fù)責(zé)訂閱orderTopic围橡,tags為A||D暖混;
? ? ? ? 2、等待一段時間翁授,待consumeA啟動完成儒恋;
? ? ? ? 3善绎、producer發(fā)送消息,發(fā)現(xiàn)consumeA正常消費(fèi)消息诫尽;
? ? ? ? 4禀酱、啟動consumeB,負(fù)責(zé)訂閱orderTopic牧嫉,tags為F剂跟;
? ? ? ? 5、producet發(fā)送消息酣藻,發(fā)現(xiàn)consumeA和consumerB都沒有消費(fèi)記錄曹洽;
? ? ? ? 6、理論上這個時候consumeA應(yīng)該能夠消費(fèi)(tags一致)辽剧,但是事實上卻沒有送淆。
原因分析
? ? 在復(fù)現(xiàn)問題以后,基本上你知道離定位問題就不遠(yuǎn)了怕轿,其實對于經(jīng)常出現(xiàn)的問題你只要靜下心去排查問題就不大了偷崩,
我的問題排查理念:
? ? 1、對mq在訂閱topic的過程和消息拉取的過程在心里要有一個宏觀的理解撞羽,說白了在心里面要清楚整個交互過程阐斜,看整個交互過程中是不是可能本身就存在這個邏輯缺陷。
? ? 2诀紊、在原來日志不能夠幫助定位你的問題的時候谒出,在可以獲取源碼的時候增加日志,增加在懷疑的執(zhí)行路徑上邻奠。
我的問題排查過程:
? ? 1笤喳、排查rocketMq訂閱消息的邏輯
? ? 2、排查rocketMq訂閱關(guān)系同步的邏輯
訂閱過程-client端:
說明:
? ? 1碌宴、在consumer端訂閱的時候我們會在本地保存一個訂閱數(shù)據(jù)杀狡,在這個訂閱數(shù)據(jù)里面有一個字段非常重要,就是用時間戳來代表的訂閱消息版本信息唧喉。
說明:
? ? 1、定時通過心跳信息發(fā)送訂閱數(shù)據(jù)到broker忍抽,也就是說我們會把訂閱信息多次發(fā)送八孝。
? ? 2、定時同步broker的訂閱信息到client端鸠项,也就是最終都會拷貝到一份最新的訂閱信息干跛。
說明:
? ? 1、在我們創(chuàng)建SubscriptionData的時候我們其實用時間戳代表了版本號祟绊,這個東西非常重要楼入,因為在broker端我們會通過版本號來區(qū)分最新數(shù)據(jù)哥捕。
訂閱過程-broker端
說明
? ? broker端處理的入口函數(shù),相當(dāng)于接收consumer的心跳數(shù)據(jù)的處理函數(shù)嘉熊。
說明:
? ? 核心關(guān)鍵點遥赚,我們每次只會用最新版本號的訂閱數(shù)據(jù)。
消息拉取-server端
說明
? ? 在broker端進(jìn)行消費(fèi)的時候我們會根據(jù)subscriptionData來判斷這個消息是否屬于tag內(nèi)的消息阐肤,如果不是指定tag的消息凫佛,就返回false直接過濾消息。
消息拉取-client端
說明
? ? client端也做了類似的過濾孕惜,不知道是處于什么考慮愧薛,但是broker端已經(jīng)對消息進(jìn)行了過濾。
結(jié)論
? ? 1衫画、同一個consumeGroup下面的多個client定時向broker發(fā)送心跳信息毫炉,匯報自己最新的subscription信息,broker端在收到消息后以最新版本的訂閱消息為準(zhǔn)削罩。??
? ? 2瞄勾、broker端在收到client拉取消息的請求后,會從broker的store中獲取消息數(shù)據(jù)并以subscription信息去進(jìn)行過濾鲸郊,這個是關(guān)鍵的地方丰榴,broker在獲取數(shù)據(jù)的時候會用最新的subscription去進(jìn)行過濾。
? ? 3秆撮、我們這個現(xiàn)象原因就是舊的subscription(tag為A||D)信息和新的subscription(tag為F)信息不一致四濒,我們以最新的subscription(tag為F)為準(zhǔn),這個時候即便你發(fā)送的消息tag為A||D职辨,在消息消費(fèi)的會因為最新的subscription(tag為F)被過濾掉盗蟆。
其他輔助信息
在消費(fèi)數(shù)據(jù)的時候會不停的打印錯誤日志:NO_MATCHED_MSG