好物分享:快速找到 Goroutine 泄露的地方
大家好,我是煎魚。
Go 語言能夠廣受大家喜歡,其中一個原因就是他的協程做的非常非常簡單,初學的入門者都可以使用。
平時只需 go 關鍵字一下,成千上萬個 goroutines 就出現了:
for ...
go func(){}
起協程就跟下餃子的。這時就個大問題,因爲協程用起來簡單,出問題出起來也很快。
也就是常常會出現 goroutine 泄露,查起來很費勁。
goleak
今天給大家推薦一個好物,定位爲純介紹。他來自 Uber 的 Goroutine leak detector[1],他能夠結合單元測試去快速的檢測 goroutine 泄露,達到避免和排查的目的。
在命令行執行第三方庫安裝:
go get -u go.uber.org/goleak
channel 會一直阻塞,導致泄露的方法:
func leak() {
ch := make(chan struct{})
go func() {
ch <- struct{}{}
}()
}
如果我們直接在常規的測試方法中調用:
func TestLeak(t *testing.T) {
leak()
}
輸出結果:
=== RUN TestLeak
--- PASS: TestLeak (0.00s)
PASS
是不會有任何變化的,正常通過測試。
這時候我們需要在代碼中添加 goleak.VerifyNone
方法,如下:
import (
"testing"
"go.uber.org/goleak"
)
func TestLeak(t *testing.T) {
defer goleak.VerifyNone(t)
leak()
}
再進行驗證:
=== RUN TestLeak
leaks.go:78: found unexpected goroutines:
[Goroutine 7 in state chan send, with github.com/eddycjy/awesome-project/tools.leak.func1 on top of the stack:
goroutine 7 [chan send]:
github.com/eddycjy/awesome-project/tools.leak.func1(0xc0000562a0)
/Users/eddycjy/go-application/awesomeProject/tools/leak.go:6 +0x35
created by github.com/eddycjy/awesome-project/tools.leak
/Users/eddycjy/go-application/awesomeProject/tools/leak.go:5 +0x4e
]
--- FAIL: TestLeak (0.46s)
FAIL
可以從報告中看到,運行結構會明確的告訴你發現泄露的 goroutine 的代碼堆棧和泄露類型,非常的省心。
另外在內部的 CI/CD 流程裏,把 goleak 結合上,對於平時的 CR 也是一個不錯的輔助。
總結
今天我們的好物分享介紹了一個小工具,能夠解決大家團隊中時長遇到的 goroutine 泄露問題,除了本文提到的 uber-go/goleak,也還有 ysmood/gotrace 等同類型的庫能夠達到類似的效果。
希望對你排查 goroutine 泄露有所幫助:)
參考資料
[1]
Goroutine leak detector: github.com/uber-go/goleak
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/E3Lgl9T8iQYl65T3e0vDTA