From 2609d07ff552a0d5229f4a006b3ceb7924d1da5b Mon Sep 17 00:00:00 2001 From: Shaobiao Lin Date: Thu, 18 Apr 2024 19:30:34 +0800 Subject: [PATCH] =?UTF-8?q?posts(timewait):=20=E8=A1=A5=E5=85=85=E8=A7=A3?= =?UTF-8?q?=E9=87=8A=E6=9B=B4=E9=80=8F=E5=BD=BB=E7=9A=84=E6=96=87=E7=AB=A0?= =?UTF-8?q?=E9=93=BE=E6=8E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../trans-tcp-time-wait-state-linux/README.md | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/posts/trans-tcp-time-wait-state-linux/README.md b/posts/trans-tcp-time-wait-state-linux/README.md index 1b15501..a451dca 100644 --- a/posts/trans-tcp-time-wait-state-linux/README.md +++ b/posts/trans-tcp-time-wait-state-linux/README.md @@ -63,7 +63,7 @@ hello XXXXhello ``` -在总结出上面这些现象后,我找了某云售后工程师咨询。对面询问我是否修改过服务器的 `net.ipv4.tcp_tw_reuse` 参数。我表示没有,同时也不知道这个参数的作用是什么。因此搜索了一番而找到上文提到的这篇文章,并且根据文章可以判断出问题在于启用了另外一个 ipv4 内核参数:`net.ipv4.tcp_tw_recycle`。 +在总结出上面这些现象后,我找了阿里云售后工程师咨询(阿里云的售后还是很专业的)。对面询问我是否修改过服务器的 `net.ipv4.tcp_tw_reuse` 参数。我表示没有,同时也不知道这个参数的作用是什么。因此搜索了一番而找到上文提到的这篇文章,并且根据文章可以判断出问题在于启用了另外一个 ipv4 内核参数:`net.ipv4.tcp_tw_recycle`。 ### 修改内核参数 @@ -330,15 +330,15 @@ $ ss -tan 'sport = :80' | awk '{print $(NF)" "$(NF-1)}' | \ ### `net.ipv4.tcp_tw_reuse` -`TIME-WAIT` 状态可以防止延迟的数据包被无关的连接所接收。然而在某些情况下,可以假设新连接的数据包不会与旧连接的数据包混淆。 +`TIME-WAIT` 状态可以防止延迟的报文被无关的连接所接收。然而在某些情况下,可以假设新连接的报文不会与旧连接的报文混淆。 [RFC1323](https://www.rfc-editor.org/rfc/rfc1323) 提出了一组 TCP 扩展,以改善在高带宽路径上的性能。其中一项是定义了一个新的 TCP 选项,它包含两个四字节的***时间戳字段***。第一个字段是发送该选项的 TCP 的时间戳时钟的当前值,而第二个字段是从远程主机接收到的最新时间戳。 通过启用 `net.ipv4.tcp_tw_reuse` 参数,Linux 会在新的***出站连接***的时间戳严格大于前一连接记录的最新时间戳时,重用处于 `TIME-WAIT` 状态的现有连接:这意味着在 `TIME-WAIT` 状态的出站连接只需等待一秒后就可以被重用。 -这样做如何保证安全?`TIME-WAIT` 状态的首要目的是避免重复的数据包被不相关的连接接收。由于使用了时间戳,此类重复的数据包将带有过时的时间戳,因此会被丢弃。 +这样做如何保证安全?`TIME-WAIT` 状态的首要目的是避免重复的报文被不相关的连接接收。由于使用了时间戳,此类重复的报文将带有过时的时间戳,因此会被丢弃。 -第二个目的是确保远端不会因为丢失最后一个 *ACK* 包而处于 `LAST-ACK` 状态。远端将重传 *FIN* 数据包,直到 +第二个目的是确保远端不会因为丢失最后一个 *ACK* 包而处于 `LAST-ACK` 状态。远端将重传 *FIN* 报文,直到 1. 等待超时,并中断连接; 2. 或者收到等待中的 *ACK*,并中断连接; @@ -358,7 +358,7 @@ $ ss -tan 'sport = :80' | awk '{print $(NF)" "$(NF-1)}' | \ 这个机制也依赖于前文提到的时间戳选项,但***同时影响入站和出站连接***。当服务器通常会先关闭连接时,这个机制会非常方便。[^tw_recycle] -此时 `TIME-WAIT` 状态会被设置更早的过期时间:它将在重传超时 *(RTO, Retransmission Timeout)* 间隔(根据 RTT 及其方差计算得出)之后被移除。可以使用 `ss` 命令观察当前连接使用的值: +此时 `TIME-WAIT` 状态会被设置更早的过期时间:它将在重传超时 *(RTO, Retransmission Timeout)* 间隔(根据 RTT (Round-Trip Time) 及其方差计算得出)之后被移除。可以使用 `ss` 命令观察当前连接使用的值: ```sh $ ss --info sport = :2112 dport = :4057 @@ -367,7 +367,7 @@ ESTAB 0 1831936 10.47.0.113:2112 10.65.1.42:4057 cubic wscale:7,7 rto:564 rtt:352.5/4 ato:40 cwnd:386 ssthresh:200 send 4.5Mbps rcv_space:5792 ``` -为了保持 `TIME-WAIT` 状态所提供的保证,同时减小过期计时器的值,当一个连接进入 `TIME-WAIT` 状态时,最新的时间戳会被记录在一个专用结构体中,该结构体包含此前目标地址的各种参数。然后,除非 `TIME-WAIT` 状态已过期,如果来自远程主机的数据包不严格大于最新记录的时间戳, Linux 就会丢弃这些数据包: +为了保持 `TIME-WAIT` 状态所提供的保证,同时减小过期计时器的值,当一个连接进入 `TIME-WAIT` 状态时,最新的时间戳会被记录在一个专用结构体中,该结构体包含此前目标地址的各种参数。然后,除非 `TIME-WAIT` 状态已过期,如果来自远程主机的报文不严格大于最新记录的时间戳, Linux 就会丢弃这些报文: ```c if (tmp_opt.saw_tstamp && @@ -384,7 +384,9 @@ if (tmp_opt.saw_tstamp && } ``` -当远程主机是 ***NAT 设备***时,这个时间戳条件就会禁止 NAT 设备后面的某一台主机之外的所有其他主机在一分钟内进行连接,因为它们不共享相同的时间戳时钟。如有拿不准,最好禁用此选项,因为它会导致***难以检测***和***难以诊断***的问题。 +当远程主机是 ***NAT 设备***时,这个时间戳条件就会禁止 NAT 设备后面的某一台主机之外的所有其他主机在一分钟内进行连接,因为它们不共享相同的时间戳时钟。如果拿不准,最好禁用此选项,因为它会导致***难以检测***和***难以诊断***的问题。 + +> 注:这里的解释不是很清楚,补充 `兔子先生` 一篇相关博文的链接:[好朋友 TIME_WAIT](https://liupzmin.com/2020/02/26/network/tcp-time-wait/) 📌 *更新 (2017-09)* @@ -404,4 +406,4 @@ if (tmp_opt.saw_tstamp && 最后引用 [W. Richard Stevens](http://www.kohala.com/start/) 在[《Unix 网络编程》](https://www.amazon.com/Unix-Network-Programming-Volume-Networking/dp/0131411551)中的一段话: -> *`TIME_WAIT` 状态是我们的朋友,它可以帮助我们(即是,使旧的重复数据包在网络中过期)。与其试图避免该状态,不如真正地理解它。* +> *`TIME_WAIT` 状态是我们的朋友,它可以帮助我们(即是,使旧的重复报文在网络中过期)。与其试图避免该状态,不如真正地理解它。*