分析根本原因
这里提出了2个问题,便于理解记忆全文。
-
为什么启用这个 tcp recycle?
-
为什么启用 tcp recycle 之后,会阻塞部分用户的连接请求?
为什么启用这个 tcp recycle?
这个是之前在部署应用主机系统时,修改优化了部分内核参数,当时想的是为了增大主机对 tcp 的连接性能,防止遇到并发用户的连接,导致 tcp 连接不能快速释放,从而引发服务器出现性能上的瓶颈(会导致服务器内存和CPU的暴增)。
因为 client 与 server 建立链接传输完数据后,会断开链接,而服务器这边还会有 2MSL 的 time_wait 时间,超过这个时间之后,正常情况下,该 socket 才会被释放, 然后才可以接收其它 client 的请求。因为 server 的端口是有固定范围的,不是说 65535 个全部都用来建立连接(可参看系统内核配置:net.ipv4.ip_local_port_range)。
另外关于 time_wait 具体的可以参考 tcp 的4次断开后的状态。所以为了快速回收和重新使用,才开启了 tcp 的 reuse 和 recycle。但没想到这个会引起这么大的问题。并且这个参数之前确实也在前公司用过。但没有发现这个类似的问题(也可能是当时的监控不到位,没有发现也不代表该问题不存在)。这里是官方内核文档对这俩参数的解释:
net.ipv4.tcp_tw_recycle: Enable fast recycling TIME-WAIT sockets. Default value is 0. It should not be changed without advice/request of technical experts.
net.ipv4.tcp_tw_reuse: Allow to reuse TIME-WAIT sockets for new connections when it is safe from protocol viewpoint. Default value is 0. It should not be changed without advice/request of technical experts.
而TIME-WAIT时间为 2MSL 的作用就是为了以确保属于未来连接的数据包不会被误认为是旧连接的延迟数据包。tcp_tw_reuse可以在TIME_WAIT 状态到期之前使用套接字,内核将尝试确保没有关于 TCP 序列号的冲突。如果启用 tcp_timestamps(默认是开启的,也就是 PAWS,用于保护包装序列号),它将确保不会发生这些冲突。
为什么会阻塞客户端(Nat 环境)请求?
上面说了为什么启用它,现在在讨论下,为什么启用它后,会导致部分用户的链接,而不是全部?看了一些文档及别人提到的解释:
当启用 tcp_tw_recycle 时,内核变得更具攻击性,并将对远程的 client 建立连接请求时使用的时间戳进行假设。它将跟踪具有 TIME_WAIT 状态连接的每个远程的 client 使用的最后时间戳, 并允许在时间戳正确增加时重新使用套接字。
但是,如果主机使用的时间戳发生更改(即 server 上记录 time_wait 中有 A 客户端的上一个请求的时间戳是 111112,现在又出现了一个 A 客户端的数据请求,并且序列号是111111.), 则 SYN 数据包将以静默的方式丢弃,并且连接将无法建立(将看到类似于“connect timeout”的错误)。
为什么我看不到关于 connect timeout 的错误呢?因为在这个环境下,client 相当于是最前面的 LB,即 haproxy,从这里也很好的解释了,为什么haproxy 的日志有很多连接重试的记录!
因为在 NAT(网络地址转换) 环境下,有很多的 client,流量进出都是通过一个公网 IP出去的。
但当多个 NAT 网络环境下的用户同时或者短时间内去访问 server 端的话, 因为对于 server 来说,此时我只知道有一个IP(client的公网IP)与我建立连接, 并且这里启用了tcp_tw_recycle,Server主机内核将认为有一部分连接请求的时间戳不是递增的,那么内核将判断该请求是无效的,就会丢失该请求。
To keep the same guarantees the TIME-WAIT state was providing, while reducing the expiration timer, when a connection enters the TIME-WAIT state, the latest timestamp is remembered in a dedicated structure containing various metrics for previous known destinations. Then, Linux will drop any segment from the remote host whose timestamp is not strictly bigger than the latest recorded timestamp, unless the TIME-WAIT state would have expired
总结
不要开启tcp_tw_recycle,重要的话说三遍。一定要有配置管理!可以方便在系统出问题时,检查对主机所做的历史记录。考虑问题不能光从 软件程序、网络上,还要加入对主机系统的分析。tcpdump、ss、还有log等。
另外,针对 Web 应用服务系统几个优化建议:
设置 net.ipv4.ip_local_port_range 合理的范围(10000~63000);
给 LB 设置更多的client IP;
配置 LB 有多个外网 IP。

(编辑:信阳站长网)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|