使用pprof分析golang內(nèi)存泄露問題及解決
問題現(xiàn)象
生產(chǎn)環(huán)境有個golang應用上線一個月來,占用內(nèi)存不斷增多,約30個G,這個應用的DAU估計最多幾十,初步懷疑有內(nèi)存泄露問題。
下面是排查步驟:
分析
內(nèi)存泄露可能點:
- goroutine沒有釋放
- time.NewTicker資源未及時釋放
- slice切割的誤用…
開啟pprof
我們的web框架使用的是gin,結(jié)合pprof
package main import ( "github.com/gin-contrib/pprof" "github.com/gin-gonic/gin" ) func main() { router := gin.Default() pprof.Register(router) router.Run(":8090") }
瀏覽器訪問:http://ip:port/debug/pprof
著重看下heap和goroutine
heap中發(fā)現(xiàn)代碼中一個內(nèi)存緩沖bigcache比較占用內(nèi)存,goroutine中發(fā)現(xiàn)總共466700個goroutine,第一處代碼占了466615個,這是肯定不正常的。至此,已基本確定內(nèi)存泄露的點了,繼續(xù)驗證:
go tool pprof http://ip:port/debug/pprof/heap
輸入top命令:
之前通過http://ip:port/debug/pprof/heap?debug=1查看到的bigcache占用內(nèi)存,go tool 分析之后排除了內(nèi)存泄露的可能性,因為程序在運行一段時間后,bigcache占用內(nèi)存并未增長,goph.NewUnknown方法的代碼位置和goroutine中client.go:72的指向是一致的,所以可以確定就是這塊代碼的問題。
代碼分析
問題代碼:
func NewUnknown(user string, addr string, auth Auth, t time.Duration) (*Client, error) { type st struct { cli *Client err error } var ch = make(chan st) # 無緩沖隊列 go func() { cli, err := NewConn(&Config{ User: user, Addr: addr, Port: 22, Auth: auth, Timeout: DefaultTimeout, Callback: ssh.InsecureIgnoreHostKey(), }) ch <- st{ # 寫阻塞 ① cli: cli, err: err, } }() for { select { case <-time.After(t): # ② return nil, fmt.Errorf("new ssh client time out") case res := <-ch: return res.cli, res.err } } }
由于ch是無緩沖的channel,①處寫數(shù)據(jù)可能會阻塞,當②超時返回時,由于ch沒有被接收方,①處的goroutine會一直阻塞,造成內(nèi)存泄露。
修復方案
var ch = make(chan st, 1)
設置一個有緩沖隊列的channel,這樣就算沒有接收方,也能往里寫數(shù)據(jù)。
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Golang 定時器(Timer 和 Ticker),這篇文章就夠了
這篇文章主要介紹了Golang 定時器(Timer 和 Ticker),這篇文章就夠了,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-10-10Golang實現(xiàn)加權(quán)輪詢負載均衡算法
加權(quán)輪詢負載均衡算法是一種常見的負載均衡策略,本文主要介紹了Golang實現(xiàn)加權(quán)輪詢負載均衡算法,具有一定的參考價值,感興趣的可以了解一下2024-08-08go mod 安裝依賴 unkown revision問題的解決方案
這篇文章主要介紹了go mod 安裝依賴 unkown revision問題的解決方案,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-05-05Golang操作sqlite3數(shù)據(jù)庫的詳細教程
最近會使用到sqlite3,這里作個記錄,記性越來越差就是這樣,下面這篇文章主要給大家介紹了關(guān)于Golang操作sqlite3數(shù)據(jù)庫的詳細教程,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下2023-04-04