Blog
Blog copied to clipboard
记一次内存泄漏的问题排查
在工作中很少能够碰到内存泄漏的问题,但是一旦遇到了,就是一个比较难解的问题, 本文旨在记录这次在问题排查的过程中,一些思路和排查方向
收到告警后,笔者先登录到告警机器中,
top
命令查看此时此刻的各个应用程序占用的内存大小,
这里其实有两个指标可以查看,
- vitr
- res
virt是虚拟内存,而 res是进程实际分配的物理内存。一般通过res查看应用内存的物理占用量, 但是你会发现,如果把每个应用程序的res加一起很有可能超过机器总内存,这是因为不同应用程序有可能引用同一个库,此时这个库被缓存,那么这两个应用程序都会将这个库所占用的内存算进去。
这时候发现,我们的node服务占用的内存是在正常范围中。
于是我们又free -g
看了下,发现used占用的内存并不多,但是buffer/cached占用的内存,超过了80%。
buffer/cached 是机器帮我们缓存的文件内容,当内存不足时,有一部分缓存是会被机器给释放掉的,也就是说,机器真正的可用内存应该是
aviliable = free + buffers + cached - 不可清空的缓存
所以不会影响业务,笔者也就长舒了一口气,可以喝杯茶再解决这个问题了。
我们目前已经知道了,是由于我们缓存区内存占用过多的问题,导致了告警,那么其实,想解决这个问题并不难,我们只需要手动释放这一部分缓存的内存就好了。
echo 3 > /proc/sys/vm/drop_caches
-
1.清除caches
-
2.清除buffer
-
3.1,2一起清除
但是这并没有真正的解决问题,因为缓存内存过多,大概率是我们代码程序中频繁读取不同的文件,导致系统帮我们缓存下来了。
因为无法直接打印出buffers/cached中缓存的内容,于是笔者开始分析代码中有可能频繁读取文件程序。
思路一
我们的程序中有一个任务是,接收不同的url,然后调用puppeteer去分析不同的页面性能。有可能是因为puppeteer在分析网页性能时,将文件缓存了下来。
于是我们想看下是否是puppeteer占用了大量的内存,我们将puppeteer装在了docker镜像中,来解决线上线下puppeteer版本的一致性以及降低线上不同机器安装puppeteer的成本。
于是我们docker ps
后拿到docker的容器id,
/sys/fs/cgroup/memory/docker/[containerid]/memory.usage_in_bytes
查看这个容器id所占用的内存并不多,发现并不是这个问题引起的。
思路二
既然cached中缓存文件过多,那么我们应该能够通过磁盘被占用的大小找出被缓存的文件,进而找到有问题的程序,毕竟12g的文件不是那么好藏的。
于是笔者在根目录下
du -sh *
发现log目录下的文件有6g,因此笔者怀疑有可能是linux将log文件缓存了下来,于是笔者将backup的log文件删除掉了,发现cached并没有减少。
问题排查到这里,笔者其实也没有什么思路了,但是这排查过程中,有两个问题,还需要确认
遗留问题
- 我们在查看docker容器中的内存,只有500多M,那么docker容器中puppeteer缓存的文件是否会缓存到宿主机上呢?如果是,那么我们查看docker所占用的内存是没有用的。
- 我们将文件删除,linux是否会将对应文件的缓存也删除了呢?
后续方向
strace pid
跟踪一个node进程id,看看一个任务进入后,会发生什么。
我的博客即将同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=2qowqqd49r8k0
有后续结果么
有后续结果么
你也遇到了这个问题吗
是哇, 求大神分析分析