NETTY對(duì)象池踩坑

? ? ? ? NETTY作為優(yōu)秀的NIO通訊框架,深受大家喜愛,在我們的發(fā)版工具項(xiàng)目啟動(dòng)時(shí),便采用其作為通訊框架,但是使用過(guò)程中卻踩了一個(gè)坑。

踩坑分析報(bào)告


項(xiàng)目簡(jiǎn)介:

在發(fā)版工具項(xiàng)目中,由于發(fā)版過(guò)程會(huì)涉及不同的發(fā)版環(huán)境,對(duì)于一次請(qǐng)求,對(duì)應(yīng)的服務(wù)提供方IP需根據(jù)此次請(qǐng)求消息的附加信息確定,同時(shí)考慮到多次請(qǐng)求建鏈的消耗過(guò)程,選擇通訊方式為長(zhǎng)連接;而考慮到連接的管理和并發(fā)控制問(wèn)題,所以加入連接池。對(duì)于NETTY通訊框架,本身已提供連接池,可通過(guò)數(shù)行代碼完成連接池定制過(guò)程,故選擇NETTY的SimpleChannelPool連接池,同時(shí)使用AbstractChannelPoolMap<InetSocketAddress,SimpleChannelPool>管理對(duì)應(yīng)不同IP地址的連接池。

異常場(chǎng)景:

連接池的使用過(guò)程為:根據(jù)請(qǐng)求數(shù)據(jù)傳入的IP信息,從AbstractChannelPoolMap中選定對(duì)應(yīng)的連接池,進(jìn)行后續(xù)通訊過(guò)程。有一次,系統(tǒng)啟動(dòng)后,異常場(chǎng)景出現(xiàn)了,傳入的IP為“36.0.12.112”,但是從MAP中通過(guò)連接池獲取連接時(shí),顯示連接IP為“36.0.12.114”?。。?/p>

異常場(chǎng)景分析:

首先,從連接池初始化過(guò)程看起,初始化代碼如下:

圖一 連接池初始化過(guò)程

該初始化過(guò)程發(fā)生在此地址對(duì)應(yīng)的第一筆交易時(shí),

圖二 根據(jù)交易信息組裝地址,獲取連接池
圖三 map內(nèi)部代碼實(shí)現(xiàn)

如此詭異的問(wèn)題,“并發(fā)問(wèn)題”首先作為了我們的首要嫌疑犯。

? ? ? ? 首先進(jìn)行場(chǎng)景的補(bǔ)全和確認(rèn)過(guò)程,測(cè)試環(huán)境的日志還在,為我們保留了完整的“犯罪”現(xiàn)場(chǎng)。從代碼看,業(yè)務(wù)代碼中存在同步調(diào)用和異步調(diào)用兩個(gè)方法,但代碼都基本類似,使用過(guò)程一般調(diào)用同步方法,即使用圖一的連接池創(chuàng)建過(guò)程。從日志來(lái)看,在進(jìn)程啟動(dòng)后,第一批交易發(fā)起過(guò)程即出現(xiàn)了該問(wèn)題,一筆請(qǐng)求對(duì)應(yīng)發(fā)送到五個(gè)不同的IP地址,則問(wèn)題應(yīng)該發(fā)生在連接池創(chuàng)建過(guò)程或者獲取過(guò)程中,但是如圖一所示,已經(jīng)使用同步代碼塊進(jìn)行控制,雖然此同步代碼塊作用不詳(此處有伏筆),創(chuàng)建過(guò)程由不同線程創(chuàng)建不同的連接池,應(yīng)該不會(huì)出現(xiàn)問(wèn)題,難道MAP存在并發(fā)問(wèn)題?然后就開始越走越遠(yuǎn),甚至懷疑人生。。。。

? ? ? ? 此時(shí),有位同事大神說(shuō),已在本地復(fù)現(xiàn),瞬間感覺要看到了光明,但瞬間又熄滅了。能復(fù)現(xiàn)問(wèn)題的測(cè)試代碼是在圖一的基礎(chǔ)上去掉了同步代碼塊,那看來(lái)同步代碼塊還是有作用的,但這并不是問(wèn)題場(chǎng)景呀。放佛又陷入了無(wú)法解決之坑,這會(huì)兒,見證了詭異現(xiàn)象的老師忽然靈光一閃,出現(xiàn)異常場(chǎng)景的時(shí)候,跟平時(shí)流程有所出入,調(diào)用的方法不是同步方法,而是異步方法,而異步方法中正好沒加入同步代碼塊控制。

圖四 異常代碼調(diào)用

? ? ? ? 終于事件大白啦,可見混亂中的場(chǎng)景復(fù)現(xiàn)是多么的重要。到此,基本可以看到坑的面貌啦,接下來(lái)就是詳細(xì)的分析過(guò)程了。

? ? ? ? 如圖四所示,連接池在初始化過(guò)程中需要傳入第一個(gè)參數(shù)為bootstrap,由于對(duì)應(yīng)IP不同,所以需要調(diào)用bootstrap.remoteAddress(paramK)進(jìn)行賦值,重點(diǎn)來(lái)了,bootsrap實(shí)例是作為該類的成員變量存在的,但是bootstrap本身并不是線程安全的。

圖五 bootstrap初始化
圖六 賦值過(guò)程

? ? ? ? 在并發(fā)情況下,該賦值過(guò)程會(huì)出現(xiàn)問(wèn)題,導(dǎo)致MAP中KEY值的IP地址與VALUE中連接池真正的地址信息不符,所以會(huì)出現(xiàn)根據(jù)地址A拿到的連接卻指向地址B的詭異現(xiàn)象。


異常場(chǎng)景分析總結(jié):

一次踩坑的排查終于結(jié)束啦,曲曲折折,不過(guò)為以后問(wèn)題排查點(diǎn)出了很多注意的事項(xiàng)。

一:一定一定一定要最大限度了解異常場(chǎng)景,不要想當(dāng)然;

二:對(duì)測(cè)試環(huán)境出現(xiàn)問(wèn)題保持敏感,并發(fā)問(wèn)題一般比較詭異,很多問(wèn)題在你放過(guò)后可能后續(xù)表現(xiàn)都正常,但是它仍然還在隱患中,可能上線后就暴露出來(lái)了,所以不要放過(guò)測(cè)試環(huán)境的詭異問(wèn)題。

最后編輯于
?著作權(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)容