背景
有同事报他的机器上nginx存在内存泄露,都吃了4G内存没法忍了,于是赶紧查查。
问题定位
1.先top -u work 查看进程内存占用情况,确认确实是占了4G没法忍了(图239M是后来补的别在意)。
2.查看nginx进程确实是业务的nginx的某个worker子进程疑似存在内存泄露占了大量内存。 ps -ef | grep nginx | grep -v grep | grep work
3.为什么不是几个worker进程都内存增大,只是个别worker进程内存占用很大? 查看日志,过滤掉干扰内容。
-
cat error.log | grep -v ‘[dns]’ | grep -v ‘access forbidden by rule’ 发现并不是那个子进程没有内存泄露,而是那个子进程频繁被kill,然后master又重启新的子进程。查询系统日志确认。
-
dmesg | grep pid 发现并不是那个子进程没有内存泄露,而是那个子进程频繁被kill,然后master又重启新的子进程。查询系统日志确认。 确认那些内存占用底的worker进程是被oom kill了,然后被master又重启新的子进程。
4.确定了是指定进程内存泄露后,查看该进程的内存分配,定位泄露信息。
- dump出改进程的内存分配,确认确实存在超大块内存分配。 pmap -x 42102
- 查看内存段的具体起始位置。 cat /proc/42102/smaps
- 通过gdb dump出那段内存存储内容。 gdb -p 4210 dump binary memory ./memory2.log 0x7fa1d0b57000 0x7FA1D0B70000
- 查看dump出的内容,发现都是某个扩展的配置数据,确定是该扩展存在内存泄露。
至此,确定是某个nginx扩展存在内容泄露,该扩展进一步分析代码定位解决。
Linux进程内存分析工具
-
top:查看机器整体内存使用情况和各进程内存使用情况。 VIRT:虚拟内存。 RES:常驻内存,一般比较关心这个。 SHR:共享内存。 DATA:数据占用内存。 参考:https://javawind.net/p131
-
pmap:pmap -x pid dump进程的内存分配情况。
-
cat /proc/pid/smaps : 查看内存块具体开始结束位置。
-
gdb -p pid 连接到进程,gdb调试,当然gdb功能非常强大。 dump binary memory ./out.log 0x7fa1d0b57000 0x7FA1D0B70000 dump出指定位置存储的内容。
-
mtrace 可以跟踪记录进程的内存分配。 参考:https://www.jianshu.com/p/d9e12b66096a