Nginx 504 问题解决 ---- 由 tcp_timestamps 导致的连接问题

这两天生产上面的一个业务遇到一个超时的问题, 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 错误,综合第二步和第三步骤,可以确定,问题可能应该出现在两个地方

  1. 前端服务器访问 LVS 的时候
  2. LVS 到 后端服务器之间

第四步

这步为了排除问题,只好是抓包解决了,使用的工具就是 tcpdumpWireshark
首先是在 前端服务器抓包,主要是抓取目的端是 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 信息,你们懂的)。

导致这个问题的详细原理,下面的参考文章已经讲的很清楚,我就不讲了。

参考文章

你可能感兴趣的:(nginx,tcp_timestamps,504,超时)