Golang 如何排查協(xié)程泄漏問題

背景

周所周知龙誊,內(nèi)存泄漏是一個(gè)很嚴(yán)重的問題,會(huì)導(dǎo)致系統(tǒng)運(yùn)行占用資源越來越多喷楣,無法釋放趟大,直至崩潰。所幸 Go 語言是一門 具有垃圾回收的語言铣焊,能大大降低遇到內(nèi)存泄漏的概率逊朽,而我們今天要說的是另外一個(gè)棘手的問題:協(xié)程泄漏。

協(xié)程泄漏:顧名思義就是出現(xiàn)了應(yīng)該釋放而沒有被釋放的協(xié)程曲伊,導(dǎo)致系統(tǒng)協(xié)程數(shù)量一直上升叽讳。不像對(duì)象回收需要引用計(jì)數(shù)、三色標(biāo)記等手段坟募,協(xié)程的回收是相當(dāng)簡(jiǎn)單的岛蚤,等待協(xié)程將代碼從頭到尾執(zhí)行完畢之后這一塊兒空間就會(huì)自動(dòng)回收,通常協(xié)程泄漏問題都是因?yàn)槟扯未a卡住了懈糯,陷入了死循環(huán)或者再等待一個(gè)不可能的條件等原因涤妒。

那么具體如何定位到到底是哪里出了問題呢,具體就要用到 Go 官方提供的性能分析工具了:pprof赚哗。

pprof

pprof 具體在 Go 語言中的實(shí)現(xiàn)是在包:runtime/pprof 中她紫,提供了諸如內(nèi)存分析硅堆、CPU分析、鎖分析等函數(shù)供調(diào)用贿讹,調(diào)用這個(gè)庫之后會(huì)將性能數(shù)據(jù)以 protobuffer 這種二進(jìn)制序列化格式導(dǎo)出渐逃。同時(shí)考慮到這一個(gè)庫較為底層,Go 官方在 runtime/pprof 上包裝提供了一個(gè)更加易用的庫:net/http/pprof民褂,提供了一種通過 HTTP 協(xié)議和性能數(shù)據(jù)交互的能力茄菊。除了性能數(shù)據(jù)的抓取工具,Golang 也提供了官方的性能數(shù)據(jù)分析工具:go tool pprof赊堪,下面我們將基于這些工具進(jìn)行一次協(xié)程泄漏問題的排查买羞。

制造協(xié)程泄漏

http.pprof 會(huì)在 init 的時(shí)候注冊(cè)一些路由到 http.DefaultServeMux 上,所以要使用這個(gè)庫雹食,我們要做的只需要引入這個(gè)包,并且使用 DefaultServeMux 監(jiān)控一個(gè)端口即可期丰,具體的話調(diào)用:http.ListenAndServe 時(shí) handler 傳空即可群叶,傳空的時(shí)候會(huì)默認(rèn)使用 DefaultServeMux 來處理。

一下是一個(gè)協(xié)程泄漏的例子钝荡,分別在第 11 行和 14 行泄漏了 1000 個(gè)協(xié)程街立。

package main

import (
    "net/http"
    _ "net/http/pprof"
)

func main() {
    for i := 0; i < 1000; i++ {
        go func() {
            select {} // 泄漏了 1000 個(gè)協(xié)程
        }()
        go func() {
            select {} // 泄漏了 1000 個(gè)協(xié)程
        }()
    }
        
        // 啟動(dòng)一個(gè) pprof http server
    if err := http.ListenAndServe(":7899", nil); err != nil {
        panic(err.Error())
    }
}

下面我們把這個(gè)服務(wù)跑起來:go run pprof.go

分析泄漏問題

我們先打開協(xié)程 Debug 的地址,我的服務(wù)監(jiān)聽在本地 7899 端口埠通,所以地址是:http://127.0.0.1:7899/debug/pprof/goroutine?debug=1赎离,通過這個(gè)我們已經(jīng)可以很明顯看到,我們的問題就發(fā)生在 pprof.go 11 行和 14 行這里端辱,泄漏了 2000 個(gè)協(xié)程梁剔,那么我們就重點(diǎn)去排查這一段代碼即可。

這個(gè)頁面很簡(jiǎn)單舞蔽,可讀性不高荣病,不過當(dāng)程序內(nèi)存狀態(tài)很復(fù)雜的時(shí)候,可以考慮配合可視化工具使用渗柿。


image.png

輸入命令:go tool pprof -http=:8001 http://127.0.0.1:7899/debug/pprof/goroutine\?debug\=1
在本地 8001 端口啟動(dòng)一個(gè) HTTP 可視化分析工具个盆,打開 http://127.0.0.1:8001/ui/ 地址,我們就能更直觀的看到所有的協(xié)程啟動(dòng)的情況:

協(xié)程分析

同時(shí)這個(gè)可視化分析工具還支持火焰圖朵栖、類 TOP 圖表等格式進(jìn)行分析颊亮,點(diǎn)擊左上角 VIEW 切換即可:


火焰圖
類 TOP 圖表

總結(jié)

pprof 可以很方便幫助我們排查協(xié)程泄漏問題,同時(shí)這套工具能干的不止如此陨溅,幾乎所有在程序性能上遇到的問題都可以使用其進(jìn)行分析终惑,想了解其他功能的話可以參考以下官方文章進(jìn)行進(jìn)一步的學(xué)習(xí):
https://blog.golang.org/pprof
https://github.com/google/pprof/blob/master/doc/README.md

原文發(fā)表于:https://huweicai.com/troubleshotting-goroutine-leeking/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市声登,隨后出現(xiàn)的幾起案子狠鸳,更是在濱河造成了極大的恐慌揣苏,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,185評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件件舵,死亡現(xiàn)場(chǎng)離奇詭異卸察,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)铅祸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門坑质,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人临梗,你說我怎么就攤上這事涡扼。” “怎么了盟庞?”我有些...
    開封第一講書人閱讀 163,524評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵吃沪,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我什猖,道長(zhǎng)票彪,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,339評(píng)論 1 293
  • 正文 為了忘掉前任不狮,我火速辦了婚禮降铸,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘摇零。我一直安慰自己推掸,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,387評(píng)論 6 391
  • 文/花漫 我一把揭開白布驻仅。 她就那樣靜靜地躺著谅畅,像睡著了一般。 火紅的嫁衣襯著肌膚如雪雾家。 梳的紋絲不亂的頭發(fā)上铃彰,一...
    開封第一講書人閱讀 51,287評(píng)論 1 301
  • 那天,我揣著相機(jī)與錄音芯咧,去河邊找鬼牙捉。 笑死,一個(gè)胖子當(dāng)著我的面吹牛敬飒,可吹牛的內(nèi)容都是我干的邪铲。 我是一名探鬼主播,決...
    沈念sama閱讀 40,130評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼无拗,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼带到!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起英染,我...
    開封第一講書人閱讀 38,985評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤揽惹,失蹤者是張志新(化名)和其女友劉穎被饿,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體搪搏,經(jīng)...
    沈念sama閱讀 45,420評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡狭握,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,617評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了疯溺。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片论颅。...
    茶點(diǎn)故事閱讀 39,779評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖囱嫩,靈堂內(nèi)的尸體忽然破棺而出恃疯,到底是詐尸還是另有隱情,我是刑警寧澤墨闲,帶...
    沈念sama閱讀 35,477評(píng)論 5 345
  • 正文 年R本政府宣布今妄,位于F島的核電站,受9級(jí)特大地震影響鸳碧,放射性物質(zhì)發(fā)生泄漏蛙奖。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,088評(píng)論 3 328
  • 文/蒙蒙 一杆兵、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧仔夺,春花似錦琐脏、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至惰蜜,卻和暖如春昂拂,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背抛猖。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工格侯, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人财著。 一個(gè)月前我還...
    沈念sama閱讀 47,876評(píng)論 2 370
  • 正文 我出身青樓联四,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親撑教。 傳聞我的和親對(duì)象是個(gè)殘疾皇子朝墩,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,700評(píng)論 2 354