1.問題出現(xiàn)場景
? ? ? ?在接手項(xiàng)目后穷吮,發(fā)現(xiàn)原系統(tǒng)長連接項(xiàng)目的心跳機(jī)制严蓖,是在Channel注冊(cè)后薄嫡,加入到系統(tǒng)的定時(shí)任務(wù)氧急,然后由服務(wù)端主動(dòng)發(fā)起心跳檢測。但重新定義線程池毫深,單獨(dú)執(zhí)行心跳任務(wù)吩坝,而且需要每10秒執(zhí)行一次,當(dāng)連接數(shù)上來時(shí)哑蔫,會(huì)因單純的心跳任務(wù)把CPU打滿钉寝。后面考慮到后端是使用Netty框架,每個(gè)Channel都會(huì)注冊(cè)到EventGroup闸迷,考慮到可以在每個(gè)Channel的注冊(cè)的線程上嵌纲,綁定一個(gè)10秒執(zhí)行的異步任務(wù)。
? ? ? ?想好就開干腥沽,功能一切正常逮走。但發(fā)布線上后,到下午今阳,發(fā)現(xiàn)服務(wù)器監(jiān)控CPU飆升至80%师溅。平時(shí)長連接服務(wù)器連接數(shù)上了,CPU占用才20%盾舌,很明顯重構(gòu)墓臭,是導(dǎo)致CPU飆升的根本原因,但這個(gè)設(shè)計(jì)思路是沒問題的妖谴,所以得排除具體是那個(gè)業(yè)務(wù)邏輯出錯(cuò)了起便。
2.線上排查
? ? ? ?首先在服務(wù)器上執(zhí)行top命令,得到CPU占用最高的進(jìn)程窖维,如下圖(非異常出現(xiàn)時(shí)的截圖)
? ? ?獲取該進(jìn)程下cpu占用最高的線程榆综。執(zhí)行命令:ps -mp 9994 -o THREAD,tid,time
? ? ?將線程號(hào)轉(zhuǎn)換成16進(jìn)制,執(zhí)行:printf "%x\n" 9996
? ? ?使用jstack命令查看堆棧日志铸史,執(zhí)行:jstack?9994 | grep 270c -A60
3.問題解決
? ? ? ?通過堆棧日志排除問題鼻疮,發(fā)現(xiàn)占用CPU最高的是Netty的 WorkEventGroup,一直在執(zhí)行心跳任務(wù),跟蹤線上當(dāng)前連接數(shù)琳轿,并沒有很多判沟。為什么連接數(shù)減少,還在一直執(zhí)行任務(wù)崭篡?發(fā)現(xiàn)挪哄,當(dāng)Channel close后,Channel從綁定的線程上注銷琉闪,但心跳任務(wù)還在繼續(xù)執(zhí)行迹炼,發(fā)現(xiàn)問題后,排查代碼,確實(shí)斯入,每個(gè)Channel在close的時(shí)候砂碉,沒有將其從任務(wù)隊(duì)列中移除,將代碼修正后刻两,發(fā)布線上增蹭,再次監(jiān)測CPU占用,OK磅摹,一切正常滋迈。
? ? ? ?任它歲月流逝,前方也定會(huì)海闊天空户誓!