生产环境服务内存透露问题考察
记录下这个问题是因为这不同于传统典型的 Go 服务内存透露。
8月15日前后,钉钉监控告警群不定时呈现服务机器内存占用超 80%
告警,一开始认为是 Prometheus exporter 沉积造成的,筹备下掉 Prometheus
exporter 的集成代码,起初觉 得这个沉积速度太快了点,不到一天就吃掉
6GB,非常夸大,所以有空的时候用 gops 快照了 一下,内存状况如下图
(pprof) /app/bin # gops memstats 1alloc: 54.66MB (57317968 bytes)total-alloc: 186.21GB (199938346560 bytes)sys: 6.72GB (7215977904 bytes)lookups: 0mallocs: 2906600570frees: 2906521966heap-alloc: 54.66MB (57317968 bytes)heap-sys: 6.44GB (6909984768 bytes)heap-idle: 6.38GB (6846406656 bytes)heap-in-use: 60.63MB (63578112 bytes)heap-released: 6.33GB (6794371072 bytes)heap-objects: 78604stack-in-use: 2.12MB (2228224 bytes)stack-sys: 2.12MB (2228224 bytes)stack-mspan-inuse: 266.02KB (272408 bytes)stack-mspan-sys: 31.88MB (33423360 bytes)stack-mcache-inuse: 6.78KB (6944 bytes)stack-mcache-sys: 16.00KB (16384 bytes)other-sys: 4.58MB (4802459 bytes)gc-sys: 251.55MB (263773240 bytes)next-gc: when heap-alloc >= 100.19MB (105060944 bytes)last-gc: 2020-08-14 20:54:01.063567774 +0800 CSTgc-pause-total: 982.706218msgc-pause: 17439num-gc: 3484enable-gc: truedebug-gc: false
剖析从下面的指标能够得出以下论断
- 以后正在应用的堆内存大抵是 60 多M
- HeapReleased = 6.33 GB 返还给操作系统的物理内存的字节数是 6.33GB (
HeapReleased 统计了从idle
span中返还给操作系统,没有被从新获取的内存大小)
那问题就形象为:\为什么 HeapReleased 回升,RSS 没有降落?\
搜寻了一下有人踩过这个坑了,参考:https://zhuanlan.zhihu.com/p/...
这是因为 Go 底层用 mmap 申请的内存,会用 madvise 开释内存。具体见
go/src/runtime/mem~linux~.go 的代码。madvise 将某段内存标记为不再应用时,有两种形式 MADV~DONTNEED~ 和
MADV~FREE~(通过标记参数传入):
- MADV~DONTNEED标记过的内存如果再次应用~,会触发缺页中断
- MADV~FREE标记过的内存~,内核会等到内存缓和时才会开释。在开释之前,这块内存仍然
能够复用。这个个性从linux 4.5版本内核开始反对显然,MADV~FREE是一种用空间换工夫的优化~。
- 在Go 1.12之前,linux 平台下 Go runtime
中的sysUnsed应用madvise(MADV~DONTNEED~)- 在Go 1.12之后,在MADV~FREE可用时会优先应用MADVFREE~
具体见 https://github.com/golang/go/...
Go
1.12之后,提供了一种形式强制回退应用MADV~DONTNEED的形式~,在执行程序前增加
GODEBUG=madvdontneed=1。具体见
https://github.com/golang/go/...
另外还有一个疑点:当初晓得问题呈现的条件是 Go \> 1.12 && Linux Kernel \>
4.5,然而 为什么之前阿里云没有呈现,零碎8月10号整体迁徙到 aws 呈现了?
考察发现
阿里云机器内核 4.4.0-105-generic,而 aws 机器内核
4.15.0-1054-aws,刚好合乎预期,能够解释。
==
补充:8月24日
应用 GODEBUG=madvdontneed=1 强制回退应用
MADV~DONTNEED~,没有再呈现内存透露问题。内存稳固在 200MB 左右