記一次內存泄露的debug過程

jdpd7627 8年前發布 | 18K 次閱讀 技術

來自: http://type.so/go/golang-debug-memory-leak.html

在壓測 代碼在線運行 工具的時候,發現當并發比較高的時候程序占用的內存會飆升,而且在中斷壓測之后,內存占用并沒有回落。

第一個能想到的辦法就是去看代碼,但是大多數時候,自己寫的代碼,很難review出太多的問題;于是就借助golang的pprof來定位問題。

在程序中嵌入 pprof

package main

import ( "tool.lu/sandbox-server/app" "net/http" _ "net/http/pprof" "strconv" "runtime" )

func main() { debug() server := app.NewApp() server.Run(":9090") }

func debug() { go func() { // 這邊是由于通過pprof發現問題之后,加的一段debug代碼;后面會講到 http.HandleFunc("/go", func(w http.ResponseWriter, r *http.Request) { num := strconv.FormatInt(int64(runtime.NumGoroutine()), 10) w.Write([]byte(num)) }) http.ListenAndServe("localhost:6060", nil) }() }</pre>

通過 go tool 工具,查看內存分配最多的 top 5

go tool pprof http://localhost:6060/debug/pprof/heap
top 5

查看代碼,發現是 goroutine, ioPipe 的問題,一定是使用姿勢出了問題:

于是便有了上面的那段代碼, curl http://localhost:6060/go ,查看當前 go routine 的數量;于是猜測是因為 ioPipe 沒有正確的關閉,引起 go routine 大量的產生,但是沒有退出,耗費大量的內存;于是在異常退出前,主動關閉 ioPipe 的Reader,至此問題解決。

壓測驗證

本機

wrk -t5 -c20 -d10000s -s post.lua http://tool.lu

服務器

curl http://localhost:6060/go

總結

這是一個很小的bug,由于寫代碼的時候不仔細,return之前沒有關閉資源造成,但卻要花費不少的力氣去解決;對語言自己提供的工具鏈需要熟悉在熟悉,這樣不管在解決問題或者避免問題的時候,都能節省很多的時間。

</div>

 本文由用戶 jdpd7627 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!