CentOS系统里TCP状态中TIME_WAIT超过3万的分析与建议

10 篇文章 1 订阅

通过如下命令,我们可以看到系统当中 TCP 状态中的情况:

$ netstat -n | awk '/^tcp/ {++state[$NF]} END {for(key in state) print key,"\t",state[key]}'
LAST_ACK     192
SYN_RECV     97
CLOSE_WAIT   2
ESTABLISHED      14418
FIN_WAIT1    389
FIN_WAIT2    1706
SYN_SENT     2
CLOSING      51
TIME_WAIT    17697

当然了,如果我们配置了系统监控,那么从 Prometheus 中看系统 TCP 状态会更加清晰。

主机上的 TCP 状态的 TIME_WAIT 数非常高,在三万到五万之间徘徊,这是相当高的,在分析问题原因以及给出解决方案之前,先来理解一下这个 TIME_WAIT 是个什么东东。

定义

我们的应用对外提供服务,当 TCP 连接主动关闭时,都会经过 TIME_WAIT 状态。TCP 四次挥手结束后,连接双方都不再交换消息,但主动关闭的一方会保持这个连接在一段时间内不可用。

分析

那么,保持这么一个状态有什么用呢?

为了理解 TIME_WAIT 状态的必要性,我们先来假设没有这么一种状态会导致的问题。暂以 A、B 来代指 TCP 连接的两端,A 为主动关闭的一端。

  • 四次挥手中,A 发 FIN, B 响应 ACK,B 再发 FIN,A 响应 ACK 实现连接的关闭。而如果 A 响应的 ACK 包丢失,B 会以为 A 没有收到自己的关闭请求,然后会重试向 A 再发 FIN 包。

此时,如果没有 TIME_WAIT 状态,A 不再保存这个连接的信息,收到一个不存在的连接的包,A 会响应 RST 包,导致 B 端异常响应。

此时, TIME_WAIT 是为了保证全双工的 TCP 连接正常终止。

我们还知道,TCP 下的 IP 层协议是无法保证包传输的先后顺序的。如果双方挥手之后,一个网络四元组(src/dst ip/port)被回收,而此时网络中还有一个迟到的数据包没有被 B 接收,A 应用程序又立刻使用了同样的四元组再创建了一个新的连接后,这个迟到的数据包才到达 B,那么这个数据包就会让 B 以为是 A 刚发过来的。

解决

从如上内容的分析中,我们在解决此类问题的时候,大致有两个方向可走,一个是控制一个 TCP 连接流程在系统当中的最大时间,一个是分配的 time_wait 容量池的最大容量,从这两个角度入手,一般就能比较好的控制系统当中 time_wait 的数量。

而上边说到的这两个参数,则都是在内核参数当中进行配置定义的。在 sysctl.conf 当中定义如下参数:

net.ipv4.tcp_fin_timeout = 20 # 设置单条TCP超时时间为20s,centos中默认为30s
net.ipv4.tcp_max_tw_buckets = 19400

在网上一些文章中,有建议将 net.ipv4.tcp_max_tw_buckets这个参数往大了调的,这种建议呢,或许在业务量小,没跑出系统性能的情况下,是合适的,但是如果在业务量庞大的场景下,我是不建议使劲儿把这个参数往大了调的,如果设置的过大(超过常规的 65535),那么很可能会影响正常的 TCP 请求,因此应该自行斟酌将此值设置在一个合理的范围当中。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CN-FuWei

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值