前言
公司一個項目中需實作以下功能:
- 讀取主程式産生的日志.
- 将日志處理後存入mongodb
實作思路大緻如下:
- 使用filewatch監視檔案,一旦檔案産生改變讀取新添加資料.
- 将讀取資料處理後存入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阻塞于這裡.
解決
後測試發現檔案監視這個包一定情況下存在這個問題,後改用檔案鎖替代,運作一段時間後沒有出現洩漏,至此問題解決.