记录一次服务器网络高延迟及严重丢包问题的排查

好久没更新了,水一篇(

最近发现服务器的网络变得非常奇怪,访问网页时经常会出现明显卡顿,有时候甚至需要等待好几秒才能打开。

本来以为只是网络抽风,结果一番折腾之后发现,问题居然是服务器 6Mbps 的公网带宽被一个下载请求吃满了。

既然前前后后查了不少东西,就简单记录一下排查过程。

问题表现

首先对服务器公网 IP 进行 Ping:

结果出现了比较严重的丢包:

一开始怀疑是宽带的问题,于是切换到手机热点重新测试。

没想到更离谱:

换了两条完全不同的网络都存在严重丢包,问题似乎并不在本地。

随后使用 Curl 测试网站的 TCP 建连时间:

正常情况下 TCP 建连只需要约 40ms:

但异常的时候会非常规律地变成:

甚至偶尔直接连接超时。

这种 1 秒、2 秒、3 秒的延迟看起来非常像 TCP 重传。

抓包看看发生了什么

TCP 建立连接需要经过所谓的“三次握手”:

其中 SYN 可以简单理解成客户端说:

我要和你建立连接。

而 SYN-ACK 则是服务器回答:

收到,可以连接。

于是我在服务器上使用 tcpdump 抓取 TCP 握手:

很快就抓到了比较有意思的东西:

服务器实际上每次收到 SYN 后,几十微秒内就发送了 SYN-ACK。

但是客户端并没有收到,所以每隔约 1 秒就重新发送一次 SYN。

刚好对应 Curl 中:

也就是说,并不是 Nginx 或网页程序处理了三秒钟,而是服务器回复的数据包在回程过程中丢掉了。

意外发现

随后查看腾讯云监控,想看看是不是有什么恶意程序在占带宽,才发现了一个之前一直没有注意的问题。

服务器公网出带宽长期保持在:

基本已经贴着 6Mbps 的上限运行。

于是使用 iftop 查看具体是谁在吃流量:

结果发现一个 IP:

同时建立了大量 HTTPS 连接,而且服务器出流量已经达到了:

进一步使用:

发现这些连接全部来自 Nginx。

最后查看 Nginx Access Log:

终于找到了罪魁祸首。

这个 IP 正在疯狂下载我的天气雷达历史数据:

每张 PNG 大约有 1MB,而且对方同时建立了大量下载连接。

于是:

这样之前所有奇怪的现象就都解释得通了。

更有意思的是,临时封禁这个 IP 后:

解除封禁后:

瞬间又把带宽打满了(

Nginx 限制下载速度

当然,永久封 IP 并不是一个很好的解决办法。毕竟用户可能真的需要下载这套数据,而且换一个 IP 又可以继续下载。这说明自建下载站还是很需要做好限速设置的,不然流量跑干净了真的是欲哭无泪。

所以最后选择在 Nginx 中对网盘的 /d/ 下载地址增加限速。

首先在 http {} 中加入:

然后单独为 /d/ 设置规则:

这样同一个 IP 理论最大速度约为:

对于只有 6Mbps 公网带宽的小鸡来说已经比较合适了,至少不会再出现一个人下载文件把整个网站一起拖死的情况。

至此问题解决。

总结

这次一开始看到高延迟和 30% 左右的 Ping 丢包,还以为是什么复杂的运营商路由或者腾讯云网络故障。

结果绕了一圈发现原因其实非常朴素:公网带宽被下载流量吃满了。

不过也顺便第一次比较完整地用 ping、curl、tcpdump、ss 和 iftop 排查了一次 TCP 网络问题,也算是学到了不少奇怪的小知识。

以后遇到非常规律的延迟,大概第一时间就会想到 TCP 重传了。

以及最后的教训:

6Mbps 真的很小

添加评论
点赞收藏
点踩分享查看原文
评论
?
参与讨论