又一次排查socket fd泄漏

距离上一次 socket fd泄漏 已经过去很久了,我再次碰到了 socket fd 泄漏的情况。相比上次的徒增,这次是缓慢增长,解决起来容易很多。这次决定换用更简单的方法,找找fd在哪泄漏的。

1 查找方法

思路是利用strace,跟踪 socket,connect,accept4,close 4个系统调用一段时间,然后用netstat查看当前连接用的inode,和 proc 下的fd inode对比,不在netstat中的inode就是泄漏的inode,最后对比strace里面记录的fd,查看这些fd是怎么创建的。写成脚本如下:

#!/bin/bash

PID=911
DURATION=3600

strace -tt -f -p $PID -e trace=socket,connect,accept4,close 2>&1 | grep -v SIGURG > tcp.log &
sleep $DURATION

netstat -tenp | grep api | sort -k 8 > netstat.txt
ls /proc/$PID/fd -l | grep socket | perl -ane '$F[10] =~ /socket:\[(\d+)\]/; print $F[8], " ", $1, "\n"' | sort -k 2 > fd.txt

for fd in $(join -v 1 -1 2 -2 8 fd.txt netstat.txt | cut -d' ' -f2); do
  F=/proc/$PID/fd/$fd
  test -e $F && {
    ls -l $F
    grep -w $fd tcp.log | tail
  }
done

2 查找问题根源

这次仍然是accept出的fd没释放,说明某些请求hang住了没有结束,亏得是go routine,系统没崩。查看go routine很容易找出问题所在。

3 思考

类似web这种服务模式,很容易出现某些接口太耗时或有BUG,导致资源逐渐耗尽的情况。监控socket fd的使用是个不错的办法。

Author: zzyongx

Created: 2020-07-07 Tue 16:16

Validate