rocketMq - tag不一致造成的假象

概述

? ? 這篇文章是以同事在實(shí)際工作中遇到的問(wèn)題作為分析的切入點(diǎn),加深自己對(duì)mq的掌握,踐行“干中學(xué)”的團(tuán)隊(duì)理念。

? ? 當(dāng)自己差不多把基本概念都掌握的差不多的時(shí)候,必須需要實(shí)際的案例或者實(shí)踐來(lái)提深自己的深度,這個(gè)時(shí)候just do it 變得很重要,所以我喜歡不停的被人挑戰(zhàn),截止目前幫人解答的問(wèn)題包括:client端消息堆積問(wèn)題、批量消息拉取問(wèn)題中遇到的神奇的數(shù)字32、以及本篇的tag不一致造成的假象,也就說(shuō)會(huì)有3篇文章輸出。

? ? 整個(gè)mq的問(wèn)題解決文章會(huì)收錄在mq的另外一個(gè)《rocketMq干中學(xué)》專題當(dāng)中,歡迎訂閱,歡迎挑戰(zhàn)。


背景

????某次線上發(fā)布升級(jí)mq的消費(fèi)端修改訂閱的topic對(duì)應(yīng)的tags,為了保證穩(wěn)定性,采取了灰度發(fā)布策略,也就說(shuō)發(fā)布一臺(tái)服務(wù)后觀察一段時(shí)間看是否正常再全量發(fā)布。

? ? 升級(jí)的內(nèi)容為consumer訂閱的tags信息,灰度一臺(tái)之后存在同一個(gè)consumeGroup下有多個(gè)consumer,且其中一個(gè)consumer的topic的tags信息和其他consumer不一致。

? ? 如我們?cè)赾onsumeGroupA下有3個(gè)consumer,一開始3個(gè)consumer訂閱了topicA + tagA||tagB,然后我們升級(jí)一個(gè)consumer訂閱topicA+tagC,這個(gè)時(shí)候在同一個(gè)consumeGroup下針對(duì)同一個(gè)topic會(huì)有兩個(gè)不同的訂閱信息。

? ? 升級(jí)以后的現(xiàn)象是什么呢,重要的事情說(shuō)3遍,說(shuō)3遍,說(shuō)3遍。

? ? 升級(jí)后我們發(fā)現(xiàn)所有的consumer都沒(méi)有消費(fèi)數(shù)據(jù)的記錄!

?????升級(jí)后我們發(fā)現(xiàn)所有的consumer都沒(méi)有消費(fèi)數(shù)據(jù)的記錄!?

????升級(jí)后我們發(fā)現(xiàn)所有的consumer都沒(méi)有消費(fèi)數(shù)據(jù)的記錄!


復(fù)現(xiàn)

????請(qǐng)按照以下順序進(jìn)行復(fù)現(xiàn)操作

????????1、啟動(dòng)consumeA,負(fù)責(zé)訂閱orderTopic,tags為A||D;

? ? ? ? 2、等待一段時(shí)間,待consumeA啟動(dòng)完成;

? ? ? ? 3、producer發(fā)送消息,發(fā)現(xiàn)consumeA正常消費(fèi)消息;

? ? ? ? 4、啟動(dòng)consumeB,負(fù)責(zé)訂閱orderTopic,tags為F;

? ? ? ? 5、producet發(fā)送消息,發(fā)現(xiàn)consumeA和consumerB都沒(méi)有消費(fèi)記錄;

? ? ? ? 6、理論上這個(gè)時(shí)候consumeA應(yīng)該能夠消費(fèi)(tags一致),但是事實(shí)上卻沒(méi)有。


consumerA


consumerB


producer


原因分析

? ? 在復(fù)現(xiàn)問(wèn)題以后,基本上你知道離定位問(wèn)題就不遠(yuǎn)了,其實(shí)對(duì)于經(jīng)常出現(xiàn)的問(wèn)題你只要靜下心去排查問(wèn)題就不大了,

我的問(wèn)題排查理念:

? ? 1、對(duì)mq在訂閱topic的過(guò)程和消息拉取的過(guò)程在心里要有一個(gè)宏觀的理解,說(shuō)白了在心里面要清楚整個(gè)交互過(guò)程,看整個(gè)交互過(guò)程中是不是可能本身就存在這個(gè)邏輯缺陷。

? ? 2、在原來(lái)日志不能夠幫助定位你的問(wèn)題的時(shí)候,在可以獲取源碼的時(shí)候增加日志,增加在懷疑的執(zhí)行路徑上。


我的問(wèn)題排查過(guò)程:

? ? 1、排查rocketMq訂閱消息的邏輯

? ? 2、排查rocketMq訂閱關(guān)系同步的邏輯


訂閱過(guò)程-client端:


消息訂閱及心跳發(fā)送

說(shuō)明:

? ? 1、在consumer端訂閱的時(shí)候我們會(huì)在本地保存一個(gè)訂閱數(shù)據(jù),在這個(gè)訂閱數(shù)據(jù)里面有一個(gè)字段非常重要,就是用時(shí)間戳來(lái)代表的訂閱消息版本信息。


說(shuō)明:

? ? 1、定時(shí)通過(guò)心跳信息發(fā)送訂閱數(shù)據(jù)到broker,也就是說(shuō)我們會(huì)把訂閱信息多次發(fā)送。

? ? 2、定時(shí)同步broker的訂閱信息到client端,也就是最終都會(huì)拷貝到一份最新的訂閱信息。


訂閱信息數(shù)據(jù)結(jié)構(gòu)

說(shuō)明:

? ? 1、在我們創(chuàng)建SubscriptionData的時(shí)候我們其實(shí)用時(shí)間戳代表了版本號(hào),這個(gè)東西非常重要,因?yàn)樵赽roker端我們會(huì)通過(guò)版本號(hào)來(lái)區(qū)分最新數(shù)據(jù)。


訂閱過(guò)程-broker端

broker端處理過(guò)程-1

說(shuō)明

? ? broker端處理的入口函數(shù),相當(dāng)于接收consumer的心跳數(shù)據(jù)的處理函數(shù)。


broker端處理過(guò)程-2

說(shuō)明:

? ? 核心關(guān)鍵點(diǎn),我們每次只會(huì)用最新版本號(hào)的訂閱數(shù)據(jù)。


消息拉取-server端

broker端處理數(shù)據(jù)拉取

說(shuō)明

? ? 在broker端進(jìn)行消費(fèi)的時(shí)候我們會(huì)根據(jù)subscriptionData來(lái)判斷這個(gè)消息是否屬于tag內(nèi)的消息,如果不是指定tag的消息,就返回false直接過(guò)濾消息。


消息拉取-client端

client端處理數(shù)據(jù)拉取

說(shuō)明

? ? client端也做了類似的過(guò)濾,不知道是處于什么考慮,但是broker端已經(jīng)對(duì)消息進(jìn)行了過(guò)濾。


結(jié)論

? ? 1、同一個(gè)consumeGroup下面的多個(gè)client定時(shí)向broker發(fā)送心跳信息,匯報(bào)自己最新的subscription信息,broker端在收到消息后以最新版本的訂閱消息為準(zhǔn)。??

? ? 2、broker端在收到client拉取消息的請(qǐng)求后,會(huì)從broker的store中獲取消息數(shù)據(jù)并以subscription信息去進(jìn)行過(guò)濾,這個(gè)是關(guān)鍵的地方,broker在獲取數(shù)據(jù)的時(shí)候會(huì)用最新的subscription去進(jìn)行過(guò)濾。

? ? 3、我們這個(gè)現(xiàn)象原因就是舊的subscription(tag為A||D)信息和新的subscription(tag為F)信息不一致,我們以最新的subscription(tag為F)為準(zhǔn),這個(gè)時(shí)候即便你發(fā)送的消息tag為A||D,在消息消費(fèi)的會(huì)因?yàn)樽钚碌膕ubscription(tag為F)被過(guò)濾掉。


其他輔助信息

在消費(fèi)數(shù)據(jù)的時(shí)候會(huì)不停的打印錯(cuò)誤日志:NO_MATCHED_MSG

心跳信息
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容