这两天生产上面的一个业务遇到一个超时的问题, nginx 的日志现象 504 超时。最后终于解决了,写这篇博客记录下,梳理下处理的整个过程。
故障排查
第一步
首先是排查 nginx 的 504 错误日志,对错误日志分析,看是否有规律,主要是统计来源 IP, URL。
结论:
排查后的结果是,出现 504 的 URL 就那么两三个,来源 IP 没有规律,根据这个找到开发人员,看是否是其请求的 URL 有问题,通过和开发人员的定位,排除了 URL 的问题,所以 URL 和 IP 方面排除出去,进行下一步
第二步
在 nginx 的日志中,新增几个日志记录字段,新增了 $upstream_status
,$upstream_response_time
,$upstream_addr
这三个字段,通过这三个字段是想判断是后端集群的所有服务器都出现 504 还是说只有部分,还有每台的超时时间是多少。
通过在 nginx.conf 配置文件的日志部分新增这三个字段后,加载 nginx ,再查看 nginx 日志发现,是所有的后端集群都出现了 504 的问题
结论:
初步推断是不是后端集群服务器的问题。
第三步
因为我这边是前端是通过域名访问的后端,所以为了进一步确定问题,我在前端集群中的一台 /etc/hosts
上面把域名和后端的真实服务器做绑定,前端集群中的其他服务器还是通过域名与 LVS 的 VIP 做绑定访问
结论:
排查后的结果是直接绑定后端真实服务器的时候,不再出现 504 错误,而其他还是通过 VIP 访问的依旧有 504 错误,综合第二步和第三步骤,可以确定,问题可能应该出现在两个地方
- 前端服务器访问 LVS 的时候
- LVS 到 后端服务器之间
第四步
这步为了排除问题,只好是抓包解决了,使用的工具就是 tcpdump
和 Wireshark
。
首先是在 前端服务器抓包,主要是抓取目的端是 LVS VIP 的
sudo /usr/sbin/tcpdump tcp -vv -i bond0 and dst host 1.1.1.2 -w ./myi.cap
在 LVS 服务器上抓包,抓取去往后端集群中服务器的包
sudo /usr/sbin/tcpdump tcp -vv and dst host 1.21.4.11 or dst host 1.21.4.12 or dst host 1.21.4.13 or dst host 1.21.4.14 -w ./user.cap
最后把抓取的包用 wireshark
查看分析。
第五步
通过抓包确定了是 LVS 到 后端服务器直接可能有问题,然后询问下其他的同事,知道这在 3 层做了 snat。印象中 LVS 相关的,在 NAT 环境的话,有一个参数可能会造成丢包。感觉 google 下,最后发现有可能是 net.ipv4.tcp_timestamps = 1
这个参数引起的。因此把 timestamps 关闭。
查看有多少包由于这个原因被拒绝了:
netstat -s |grep rejects
172 packets rejects in established connections because of timestamp
sudo vim /etc/sysctl.conf # 在该文件最后加入以下
net.ipv4.tcp_timestamps = 0
###生效
sudo /sbin/sysctl -p
最后观察日志,504 消失,问题解决。不禁哀嚎,我也终于遇到这个问题。不过总算解决了。此文只是一个我的分析排查过程,具体的报文什么的就不贴了,因为我懒得涂鸦关键字(涉及一些 IP 信息,你们懂的)。
导致这个问题的详细原理,下面的参考文章已经讲的很清楚,我就不讲了。