使用strace排查Nginx启动缓慢问题

在某台新服务器上,发现Nginx启动/重启耗时非常长。相同的配置复制到其他服务器,几乎在瞬间就能完成启动/重启操作,说明新服务器的行为不正常。进一步测试,发现 nginx -t
测试命令耗时也很长,需要找到原因以解决问题。

Linux系统可以使用 strace
命令跟踪进程的系统调用,从而排查可能出现问题的地方。由于 nginx -t
的耗时也很长,就从这个单次命令看看能不能找出问题关键。

执行命令 strace -T nginx -t
,其中 -T
参数打印耗时,在进程卡住的地方发现如下输出:

connect(7, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("x.x.x.x")}, 16) = 0 
poll([{fd=7, events=POLLOUT}], 1, 0) = 1 ([{fd=7, revents=POLLOUT}]) 
sendmmsg(7, [{msg_hdr={msg_name=NULL, msg_namelen=0, msg_iov=[{iov_base="\223\310\1\0\0\1\0\0\0\0\0\0\4ocsp\10digicert\3com\0\0"..., iov_len=35}], 
msg_iovlen=1, msg_controllen=0, msg_flags=0}, msg_len=35}, {msg_hdr={msg_name=NULL, msg_namelen=0, msg_iov=
[{iov_base="I\320\1\0\0\1\0\0\0\0\0\0\4ocsp\10digicert\3com\0\0"..., iov_len=35}], 
msg_iovlen=1, msg_controllen=0, msg_flags=0}, msg_len=35}], 2, MSG_NOSIGNAL) = 2 
poll([{fd=7, events=POLLIN}], 1, 5000) = 0 (Timeout) <5.005221>

从行尾输出看到,这个系统调用耗时5.005221秒,大概率就是问题所在。
那么上面的输出信息能看出什么呢?

首先看 connect
这行中的 sin_port=htons(53)
,其中53是DNS查询端口,说明系统发起了DNS查询;再看第二行 sendmmsg
中的 iov_base="\223\310\1\0\0\1\0\0\0\0\0\0\4ocsp\10digicert\3com
,携带了证书的OCSP域名,猜测是向DNS服务器发起查询请求;最后的一行 poll
Timeout
提示,说明查询超时,整个过程总共耗时5.005221秒。
总结上述信息:系统向x.x.x.x发起证书OCSP域名的DNS查询请求,但是DNS超时未响应,导致耗时很长。

终端ping该DNS服务器的IP地址,无法ping通;打开 /etc/resolv.conf
,看到该IP地址写在第一行,于是将其注释掉。

接下来再运行 nginx -t
命令,瞬间完成;接着测试启动、重启Nginx,几乎也是瞬间完成,说明问题解决。