項(xiàng)目背景:
大型內(nèi)部管理項(xiàng)目
項(xiàng)目特點(diǎn):
單個(gè)客戶請(qǐng)求量很大,平均每個(gè)客戶在登錄過(guò)程中會(huì)產(chǎn)生大致70+左右的請(qǐng)求及一條長(zhǎng)鏈接建立
(由于開(kāi)發(fā)環(huán)境為內(nèi)網(wǎng)環(huán)境,無(wú)法將排查過(guò)程的截圖展示出來(lái))
問(wèn)題描述:
在測(cè)試過(guò)程中發(fā)現(xiàn),服務(wù)正常的情況下,沒(méi)有請(qǐng)求到達(dá)服務(wù)端。所有請(qǐng)求會(huì)有報(bào)錯(cuò)為網(wǎng)絡(luò)超時(shí)。
重啟可以讓服務(wù)正常,但持續(xù)不了多久,上述情況依舊會(huì)出現(xiàn)。
請(qǐng)求鏈路為:
web -> ng -> admin管理臺(tái)服務(wù) -> 其他服務(wù)
排查過(guò)程:
1.排查nginx是否正常,通過(guò)查詢nginx日志可以看出,請(qǐng)求正常轉(zhuǎn)發(fā)。但服務(wù)端無(wú)響應(yīng)日志
2.排查服務(wù)日志,經(jīng)過(guò)查看發(fā)現(xiàn)最后卡住的線程號(hào)都比較大,說(shuō)明沒(méi)有線程被釋放從而導(dǎo)致阻塞。在此處做了很多功夫,耽誤了不少時(shí)間,比如修改最大線程,修改超時(shí)時(shí)間等。但最后發(fā)現(xiàn)只能減少問(wèn)題出現(xiàn)的時(shí)間,并不能避免問(wèn)題,說(shuō)明本質(zhì)問(wèn)題不在此。但不代表如果遇到相同情況的同學(xué)可以忽略這步驟。
3.jstack 命令排查堆棧信息,在此操作之前,也查看了GC,但并沒(méi)有發(fā)現(xiàn)問(wèn)題,所以不做過(guò)多贅述。在排查堆棧信息的過(guò)程中,發(fā)現(xiàn)很多線程狀態(tài)為WATTING,無(wú)限期等待,說(shuō)明此部分線程,可能混雜著正常與非正常的線程。其中發(fā)現(xiàn)RUNNING狀態(tài)的線程多為Redis相關(guān)線程。
4.修改redis連接超時(shí)時(shí)間等參數(shù),來(lái)測(cè)試redis的鏈接是否出現(xiàn)問(wèn)題,經(jīng)測(cè)試未發(fā)現(xiàn)問(wèn)題。
5.此時(shí)能確定問(wèn)題的根本與redis有關(guān),但不清楚具體哪些情況下會(huì)出現(xiàn)問(wèn)題,從而繼續(xù)排查服務(wù)日志,發(fā)現(xiàn)了關(guān)鍵點(diǎn)
"所有被阻塞的線程均與數(shù)據(jù)庫(kù)連接相關(guān)!"
6.立刻想到了既用到Redis又用到了數(shù)據(jù)庫(kù)連接的序列服務(wù),返回堆棧信息確實(shí)發(fā)現(xiàn)了被阻塞的事務(wù)相關(guān)類
7.排查序列服務(wù)代碼,發(fā)現(xiàn)均加了事務(wù)控制信息。進(jìn)行并發(fā)模擬,發(fā)現(xiàn)在使用過(guò)程中,所寫(xiě)涉及事務(wù)代碼優(yōu)化部分會(huì)導(dǎo)致占用數(shù)據(jù)庫(kù)連接,導(dǎo)致數(shù)據(jù)庫(kù)連接池?zé)o法產(chǎn)生新的數(shù)據(jù)庫(kù)連接。
至此,問(wèn)題解決,優(yōu)化了事務(wù)獲取獲取redis鎖邏輯等相關(guān)邏輯