天天看點

記一次golang記憶體洩露問題修複

前言

公司一個項目中需實作以下功能:

  1. 讀取主程式産生的日志.
  2. 将日志處理後存入mongodb

實作思路大緻如下:

  1. 使用filewatch監視檔案,一旦檔案産生改變讀取新添加資料.
  2. 将讀取資料處理後存入mongodb.

問題

程式運作一段時間後發現系統變的巨卡,檢視程序管理發現此程序占用大部分記憶體,再次估計是發生記憶體洩露,開始查找問題.

在程式中加入記憶體消耗分析

fm, err := os.OpenFile("./mem.out", os.O_RDWR|os.O_CREATE, 0644)
if err != nil {
    log.Fatal(err)
}
pprof.WriteHeapProfile(fm)
fm.Close()
           

分析後發現大部分記憶體配置設定在watcher.WaitForFileChange()内部,然後繼續使用net/http/pprof

_ net/http/pprof
go func() {
    http.ListenAndServe("localhost:6060", nil)
}()
           

使用網頁檢視,發現有大量的goroutine阻塞于watcher.WaitForFileChange().至此發現是因為檔案監視當檔案發生改變後沒有傳回,導緻大量goroutine阻塞于這裡.

解決

後測試發現檔案監視這個包一定情況下存在這個問題,後改用檔案鎖替代,運作一段時間後沒有出現洩漏,至此問題解決.