一次Prometheus采集器内存占用过高(内存泄漏)问题排查及解决

一、背景介绍

        我参与的一个项目使用了腾讯的云存储组件CSP。我们需要利用Proemtheus Exporter对改组件进行监控。由于没有找到相关的采集器,我们团队自己开发了一款CSP Exporter。该采集器由我所在团队的一位大佬开发出了初版。采集器上线两个月后,用户反馈该采集器占用了大量的系统内存,重启后该问题消失。此时该大佬已经离职另谋高就,排查该问题的任务落到了我的头上。经过一周的不懈努力,最终定位到并解决了该问题,以下是排查及解决的过程。

二、问题定位

       发现问题的过程是用户反馈该采集器占用了系统大量内存资源,如图1所示。

图1

       刚接到这个问题时,第一反应想到,是不是因为代码里面某个地方申请了资源后没有释放而导致的。因为该采集器是由GO语言开发,而GO有自己的GC机制,所以我当时首先判断动态申请了内存后没有释放的概率是比较小的,因为这一部分GO自己完成了。

       持续观察一段时间后,发现内存使用是在不断增加的。这一点很可疑,是什么会让资源不断增加?联想到采集器采集数据的机制,每隔30秒监控系统的Prometheus会向该采集器发起一次请求,采集器在收到请求后,会向在云端的CSP组件发起若干请求来获取数据。再回想起以往一次排查ES故障的经历,ES由于打开的文件描述符太多,从而导致占用了过多的内存。这时突然灵光一现,想到会不会是因为采集器每次与云上的CSP建立了TCP连接后没有释放。而每建立一次TCP连接,Linux就会打开一个文件描述符,如果打开的TCP连接一直没有关闭,就会占用系统资源,包括内存资源。想到这里,立马开始查看该采集器打开的连接情况。首先使用lsof命令查看该进程打开的文件数量情况,如图2。

图2

果然,该采集共计打开了一百四十多万个文件,这显然是不正常的。再看打开的都是哪些文件(图3):

图3

可以看到,输出中基本都是处于ESTABLISED状态的TCP连接。为了进一步验证这些连接是会不断增加的,我在本地向该采集器多次发起请求。我观察到,一方面其process_open_fd指标值是不断增加的,另一方面,lsof -c csp_exporter的条目数量也是不断在增加的,且均为状态为ESTABLISHED的TCP连接,并且连接的目的地址就是云CSP的地址。如图4、图5和图6

图4

图5

图6

由此,我们基本可以确定,问题的发生是由于代码某个位置向云端的CSP发起请求后建立了TCP连接,请求完成后连接没有关闭引起的。定位到了问题,接下来只需找到向CSP发起请求的位置并增加一行关闭连接的代码即可。

三、问题解决

        该采集器共提供了九个指标,每一个指标数据的获取都是通过COS SDK请求云端的CSP服务得到,如图7。

图7

第100行代码向云端CSP服务发起请求获取数据。直到代码的末尾都没有看到客户端主动关闭连接的代码。从第161行到结束,我们增加了客户端主动断开连接的代码。每一次获取到云端CSP返回的数据后主动断开连接。

图8

      在增加了这几行代码后,我们更新了生产环境的采集器,运行一段时间后我们观察到新采集器的文件描述符打开数一直稳定在13(图9),并且内存使用情况也趋于稳定。因此我判断我们的解决方法生效了。

图9

      至此,团队内部开发的CSP采集器内存资源占用过高的问题(内存泄漏)初步判断已解决。最终确定发生的原因是:采集器没有主动关闭与云端CSP组件建立的TCP连接导致占用系统资源;解决方式是在代码中增加主动关闭连接的代码。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值