Contents

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释放.