pprof是Go语言自带的性能分析工具,也是排查内存泄漏的核心工具。需在代码中导入net/http/pprof包并启动HTTP服务器,暴露内存分析接口:
package main
import (
"log"
"net/http"
_ "net/http/pprof" // 自动注册pprof路由
)
func main() {
go func() {
log.Println(http.ListenAndServe("localhost:6060", nil)) // 启动pprof服务器
}()
// 你的应用代码...
}
这一步会开启/debug/pprof/端点,后续通过该端点获取内存数据。
go tool pprof http://localhost:6060/debug/pprof/heap
top:按内存占用排序显示函数,找出占用最高的内存函数(如泄漏函数的调用栈顶部)。list <函数名>:查看指定函数的详细内存分配情况(如某行代码分配了大量内存)。web:生成SVG格式的内存引用图(需安装graphviz),直观展示内存泄漏的调用链。Goroutine泄漏(未正常退出的Goroutine持有内存)是Golang内存泄漏的常见原因。通过pprof的goroutine端点分析:
go tool pprof http://localhost:6060/debug/pprof/goroutine
在交互界面中使用top查看Goroutine数量异常增长的函数,list查看具体调用栈,重点检查是否有未关闭的channel、未退出的循环或未释放的锁。
通过runtime包定期记录内存使用情况,将数据写入日志,观察内存是否持续增长(泄漏的典型特征):
import (
"log"
"runtime"
)
func logMemoryUsage() {
var m runtime.MemStats
runtime.ReadMemStats(&m)
log.Printf("Alloc=%v MiB, TotalAlloc=%v MiB, Sys=%v MiB, NumGC=%v",
m.Alloc/1024/1024, m.TotalAlloc/1024/1024, m.Sys/1024/1024, m.NumGC)
}
在应用的关键节点(如每分钟)调用logMemoryUsage(),若Alloc(当前分配内存)或TotalAlloc(累计分配内存)持续增长,需进一步用pprof分析。
结合Prometheus+Grafana搭建实时监控系统,采集以下指标:
go_memstats_alloc_bytes)go_memstats_heap_alloc_bytes)go_goroutines)go_memstats_num_gc)go-torch生成火焰图,可视化内存分配的热点函数,直观展示内存泄漏的代码路径(如某函数占用了大量堆内存)。Close()方法。GOGC环境变量调整垃圾回收频率(如export GOGC=50,降低阈值可更频繁触发GC,但会增加CPU开销)。