tcp_syn_retriesnet.ipv4.tcp_syn_retries
什么是 tcp_syn_retries? tcp_syn_retries 是 Linux 内核中的一个内核参数,用于控制 TCP 协议在发送 SYN 包时的重试次数。当一个 TCP 连接请求(SYN 包)未收到对方的响应时,内核会根据该参数的设置决定重试发送 SYN 包的次数。
该参数的默认值是多少? 默认值通常为 6,这意味着内核会尝试发送 SYN 包最多 6 次。 TCP 的超时重传机制遵循 指数退避 (Exponential Backoff) 原则。 第一次发送 SYN 后,如果没有响应:
第一次重试:1 秒后
第二次重试:2 秒后
第三次重试:4 秒后
第四次重试:8 秒后
第五次重试:16 秒后
第六次重试:32 秒后 因此,默认情况下,tcp_syn_retries 设置为 6 意味着在最坏情况下,对应 67(tcp_syn_linear_timeouts = 4) 秒(1 + 2 + 4 + 8 + 16 + 32 + 4),此时初始 RTO 为 1 秒。因此,TCP 连接尝试的最终超时时间为 131 秒。
官方链接
抓包分析
# 尝试连接一个不存在的 IP(或者被防火墙 DROP 的 IP),同时用 tcpdump 抓包。 # 终端 1: 抓包 tcpdump -i eth0 dst port 80 -n # 终端 2: 发起连接 (假设目标 IP 192.168.1.99 不可达) curl 192.168.1.99
抓包结果会显示多次 SYN 包的发送,间隔时间逐渐增加,直到达到 tcp_syn_retries 设置的次数为止。
Flags [S]: 所有的包都是 SYN 包,说明握手一直没成功。源端口不变 (45678): 注意看 10.0.0.5.45678,源端口始终是 45678。这证明了这些包属于同一个连接请求,而不是新的请求。如果是应用层重试(例如 curl 超时后重试),源端口通常会变。时间间隔 (指数退避): 注意每个 SYN 包发送的时间间隔逐渐增加,符合指数退避的规律。查看和修改
查看当前值:
sysctl net.ipv4.tcp_syn_retries临时修改该值(需要 root 权限):
sysctl -w net.ipv4.tcp_syn_retries=5
永久修改:编辑
/etc/sysctl.conf文件,添加或修改以下行:net.ipv4.tcp_syn_retries = 5
然后运行
sysctl -p使更改生效。
最佳实践
✅ 场景一:内网微服务 (推荐值: 1 或 2)在数据中心内部,网络非常稳定,延迟极低(毫秒级)。 如果 1-2 次重试(约 3-7 秒)都连不上,基本可以判定对方挂了或者网络断了。 建议设为 2。重试 2 次总耗时:1 + 2 + 4 = 7秒。相比 127 秒,快速失败 (Fail Fast) 能让你的应用有机会尝试其他节点,或者迅速降级。
✅ 场景二:跨公网/弱网环境 (推荐值: 4 或 5)如果是移动端连接服务器,或者跨国链路,网络抖动是常态。 这时候如果重试次数太少,稍微丢个包连接就断了,用户体验会很差。 建议保持默认值,或者设为 4。区分混淆
tcp_syn_retries vs tcp_synack_retries:tcp_syn_retries 控制的是本端发送 SYN 包的重试次数,而 tcp_synack_retries 控制的是本端在收到对方 SYN 后,发送 SYN-ACK 包的重试次数。两者针对的是 TCP 握手的不同阶段。
应用层重试 vs 内核层重试:应用层(如 curl、浏览器等)可能会有自己的重试机制,这通常会导致源端口变化。而内核层的 tcp_syn_retries 重试是针对同一个连接请求,源端口保持不变。
区分 tcp_retries2:tcp_syn_retries 是管建立连接时的重试;而 tcp_retries2 是管连接建立后传输数据时的重试。