Go語(yǔ)言之使用pprof工具查找goroutine(協(xié)程)泄漏
用pprof工具查找goroutine(協(xié)程)泄漏
goroutine泄漏指的是goroutine啟動(dòng)之后沒有退出導(dǎo)致goroutine的數(shù)量持續(xù)上升,或者是在實(shí)際應(yīng)用中g(shù)oroutine占用了很長(zhǎng)時(shí)間才退出導(dǎo)致在一段時(shí)間內(nèi)goroutine的數(shù)量急劇上升。
通??梢圆捎肎o自帶的pprof工具來定位問題
如下面這個(gè)示例
這是一個(gè)簡(jiǎn)單的HTTP服務(wù),當(dāng)接收到請(qǐng)求時(shí)另起一個(gè)goroutine來輸出日志,同時(shí)返回“Hello, World!\n”。
在記錄日志之前可能要處理一個(gè)耗時(shí)很長(zhǎng)的業(yè)務(wù)邏輯,如通過公網(wǎng)請(qǐng)求第三方的API接口,這里為了簡(jiǎn)化問題用time.Sleep來示意。
goroutineleak.go
package main
import (
"io"
"log"
"net/http"
_ "net/http/pprof"
"time"
)
func writeLog(msg string) {
go func() {
time.Sleep(1 * time.Second)
log.Println(msg)
}()
}
func handler(w http.ResponseWriter, r *http.Request) {
writeLog(r.URL.RequestURI())
io.WriteString(w, "Hello, world!\n")
}
func main() {
http.HandleFunc("/", handler)
http.ListenAndServe(":8080", nil)
}利用Grinder來壓測(cè),開8個(gè)進(jìn)程,每個(gè)進(jìn)程開3個(gè)線程,同時(shí)請(qǐng)求上述服務(wù)。
在請(qǐng)求過程中,通過瀏覽器查看http://pub.pengpengzhou.com:8080/debug/pprof/goroutine?debug=1, 域名是上述服務(wù)所在的地址。

從pprof的返回結(jié)果中,我們可以看到協(xié)程總數(shù)是5605,下面列出了5組產(chǎn)生協(xié)程的代碼stack trace,按產(chǎn)生的協(xié)程數(shù)量倒排序。
可以看到第一組產(chǎn)生了5597個(gè)協(xié)程,產(chǎn)生位置在goroutineleak.go的13行“time.Sleep(1 * time.Second)”對(duì)應(yīng)的函數(shù)是main.writeLog。
問題很快得到定位,把這一行注釋掉,重新再壓測(cè),可以得到如下結(jié)果, 協(xié)程總數(shù)一下就降到了8,泄漏的問題得到了解決。

當(dāng)然,在實(shí)際應(yīng)用中,耗時(shí)是不可避免的,通常是用設(shè)置超時(shí)的辦法來規(guī)避長(zhǎng)時(shí)間等待。
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
- Go語(yǔ)言輕量級(jí)線程Goroutine用法實(shí)例
- go獲取協(xié)程(goroutine)號(hào)的實(shí)例
- go中控制goroutine數(shù)量的方法
- Golang 探索對(duì)Goroutine的控制方法(詳解)
- Go 防止 goroutine 泄露的方法
- 淺析Golang中的協(xié)程(goroutine)
- golang goroutine順序輸出方式
- Go語(yǔ)言死鎖與goroutine泄露問題的解決
- Go語(yǔ)言CSP并發(fā)模型goroutine及channel底層實(shí)現(xiàn)原理
- go語(yǔ)言面試之Goroutine詳解
相關(guān)文章
Go語(yǔ)言學(xué)習(xí)之接口類型(interface)詳解
接口是用來定義行為的類型,定義的行為不由接口直接實(shí)現(xiàn),而由通過方法由定義的類型實(shí)現(xiàn),本文就來和大家詳細(xì)講講Go語(yǔ)言中接口的使用吧2023-03-03
go goroutine 怎樣進(jìn)行錯(cuò)誤處理
在 Go 語(yǔ)言程序開發(fā)中,goroutine 的使用是比較頻繁的,因此在日常編碼的時(shí)候 goroutine 里的錯(cuò)誤處理,怎么做會(huì)比較好呢,本文就來詳細(xì)介紹一下2021-07-07
Go實(shí)現(xiàn)跨平臺(tái)的藍(lán)牙聊天室示例詳解
這篇文章主要為大家介紹了Go實(shí)現(xiàn)跨平臺(tái)的藍(lán)牙聊天室示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-12-12
Go?Gin框架優(yōu)雅重啟和停止實(shí)現(xiàn)方法示例
Web應(yīng)用程序中,有時(shí)需要重啟或停止服務(wù)器,無(wú)論是因?yàn)楦麓a還是進(jìn)行例行維護(hù),這時(shí)需要保證應(yīng)用程序的可用性和數(shù)據(jù)的一致性,就需要優(yōu)雅地關(guān)閉和重啟應(yīng)用程序,即不丟失正在處理的請(qǐng)求和不拒絕新的請(qǐng)求,本文將詳解如何在Go語(yǔ)言中使用Gin這個(gè)框架實(shí)現(xiàn)優(yōu)雅的重啟停止2024-01-01
Go語(yǔ)言函數(shù)的延遲調(diào)用(Deferred Code)詳解
本文將介紹Go語(yǔ)言函數(shù)和方法中的延遲調(diào)用,正如名稱一樣,這部分定義不會(huì)立即執(zhí)行,一般會(huì)在函數(shù)返回前再被調(diào)用,我們通過一些示例來了解一下延遲調(diào)用的使用場(chǎng)景2022-07-07
golang 如何用反射reflect操作結(jié)構(gòu)體
這篇文章主要介紹了golang 用反射reflect操作結(jié)構(gòu)體的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2021-04-04
Ruby序列化和持久化存儲(chǔ)(Marshal、Pstore)操作方法詳解
這篇文章主要介紹了Ruby序列化和持久化存儲(chǔ)(Marshal、Pstore)操作方法詳解,包括Ruby Marshal序列化,Ruby Pstore存儲(chǔ),需要的朋友可以參考下2022-04-04

