背景
上个月,有一个跑了很久的服务,突然出现部分机器疯狂内存增长的现象,查看了最近2个月的提交记录,均无发现可疑的情况。排查了上下游的上线情况,也排查了上下游导致的内存情况。
这个服务,其实我也不是很熟悉业务,一方面是我入职后需求不是特别多,另一方面能够问的同事比较少,因为之前相关的人基本在我入职前后就都已离职了。
但是一开始还是挺有自信的,因为排查内存的工具还是挺多的。
排查过程
但是过程并没有那么顺利。
首先想到的是采用的是 valgrind ,但是并没有那么理想。首先我在测试环境测试,并没有复现。其次我在线上环境的时候发现一旦启动了valgrind。由于valgrind导致服务的性能急剧下降(之前看到的文献是能下降了20-30倍), 导致在复杂的线上环境中,一旦启动了valgrind我们的这个服务根本无法正常运行。
bcc套件中还有一个体验更好的工具memcheck, 但是官网提示需要centos7.6之后的内核才能支持。 查了几篇文章,发现有人在7.5上也成功了。所以尝试在7.5的机器上安装,但最后失败。
于是看起来只能通过其他工具来检测。
想到内存泄漏会不会有什么规则,比如每隔一段时间增大多大。这样再根据strace可以找到这部分内存使用的内存的目的,这样也就有了相关线索。
于是用pidstat 对进程进行了内存检测。
但是从秒级到小时级别的检测,均未发现相关线索。
以上方案是我之前排查内存泄漏时候用的主要方式,之前可谓是屡试不爽。但是在这次内存泄漏的排查过程中折了腰。当时心想吃的盐还是太少了。无奈下只能Google。
Google最终的确没让我失望, 发现我们使用的jemalloc中带有一个jeprof的工具。它有一个很大的好处就是不仅可以profile进程当时整个状态的内存使用分布情况, 这样的如果有内存泄漏其实一目了然。
jeprof的使用很简单,首先不需要修改或者植入任何代码。但是如果之前使用的jemalloc没有打开enable prof功能需要重新编译。在启动的时候添加一下参数,然后会生成对应的profile文件供你进行分析。具体这边就不介绍了,可以另行google,网上资料不少。
但是我这有一个疑问目前还没解决,jeprof是不是对内核也有一定要求,因为我在centos 6的机器上使用的时候发现最后的绘图只有address没有显示具体symbols。
总结
jeprof工具大概会影响进程一半的性能,在调试的过程最好将服务的qps调低到平常正常的一半
可以每隔一段时间画一个内存Profile图来分析,我这边在最近一次无聊的中,又新发现了一个内存泄漏(有一个对象没有写析构函数)。通过分析jeprof的内存分布图,可以找到很多平时可能顾及不到的内存问题。