Go 内存泄漏排查
背景
某次发版后,生产机器的内存相比之前相同负载条件下使用率高,业务无异常影响. 而后带来的影响是,数据库连接资源随着pod数量提升占用提高.
间接处理
- 回滚版本
- 每隔固定时间定时重新发版
- 把所有依赖pkg升级至最新,把Go版本升级至最新
- 服务拆分,让业务链路保持简单.
直接处理
- 排查内存泄漏与修复
思路
复现生产环境场景
在测试环境里,对比此次版本的功能改动点进行压测,难以压测的直接for循环将变动函数调用增加10倍来调试或者将time.ticker的频率放大10倍.
使用pyroscope分析
pyroscope https://pyroscope.io/ 是基于golang的pprof
工具进行采集.
使用pprof
go官方自带的工具 https://github.com/google/pprof
使用perf
perf是个经典的分析工具, https://github.com/google/perf_data_converter 可以将perf
的分析报告转化为pprof
的格式进行分析
pprof着手分析
下载heap分析文件
接入pprof后,可用curl
下载分析文件 curl -o heapfile http://localhost/debug/pprof/heap?seconds=30
.
上述命令可捕获30秒的堆文件分析.
查看pprof官方自带文档
关于pprof的使用说明,请务必看完 https://github.com/google/pprof/blob/main/doc/README.md 该文讲述了
- pprof字段
flat
cum
代表的含义. - 可通过web的方式进行UI交互或者cli方式交互.
go tool pprof -http :8810 heapfile
- 调用图里面的颜色,矩形大小,矩形边缘粗细,虚线箭头和实线箭头的含义解释
- 可对比2个时间段的pprof文件,
go tool pprof --base base.heap current.heap
内存采样率控制
runtime.MemProfileRate 采样率控制.
假设runtime.MemProfileRate=N,那么采样为1/N进行.如果觉得采样率小了,可以在测试环境进行调整.
空闲 Heap
http://localhost/debug/pprof/heap?debug=1 有个HeapIdle
指标.
下载go官方源码用IDE打开即可明白各个指标的含义,比如HeapIdle .
HeapIdle
= HeapSys
- heapInUse
我们可以用htop
查看go程序进程,其中htop里面的RES
为真实的内存占用.
HeapSys
占了go程序的内存大头,理论上是接近go应用相关进程的RES
.
pprof工具是不会展示HeapIdle
部分,因为HeapIdle
是go应用可以复用的内存,我们可以手动runtime.GC()
进行空闲Heap释放.