tcp_slow_start_after_idle 默认开启导致空闲连接恢复时退回到慢启动,吞吐骤降;应设为0并持久化。

tcp_slow_start_after_idle 导致连接吞吐突然下降
Linux 默认开启 tcp_slow_start_after_idle,空闲连接重传时会退回到慢启动状态——哪怕之前已跑满带宽。这不是 bug,是 RFC 规定行为,但对长连接、RPC 调用、数据库连接池等场景很不友好。
实操建议:
- 确认当前值:
sysctl net.ipv4.tcp_slow_start_after_idle(默认为 1) - 关闭它:
sysctl -w net.ipv4.tcp_slow_start_after_idle=0,并写入/etc/sysctl.conf持久化 - 注意:仅影响空闲后恢复的连接,不影响新建连接;内核 4.1+ 支持该参数,老版本需升级或绕过
net.core.somaxconn 和应用 listen() 的 backlog 不匹配
应用调用 listen(fd, backlog) 时传的 backlog 值,会被内核截断为 net.core.somaxconn 的最小值。若应用设了 1024,但系统值是 128,实际队列长度就是 128——SYN 队列溢出直接丢包,表现为偶发连接超时或拒绝。
实操建议:
- 查当前限制:
sysctl net.core.somaxconn,同时用ss -lnt看实际监听队列长度(Recv-Q列) - 调高它:
sysctl -w net.core.somaxconn=4096;Go/Java 等语言默认 backlog 常为 50~128,务必同步检查应用层配置 - 注意:Docker 容器内需在 host 或 cgroup 层设置,容器启动时
--sysctl可透传,但部分托管平台(如 EKS)可能拦截
net.ipv4.tcp_tw_reuse 在 NAT 环境下引发 TIME_WAIT 冲突
net.ipv4.tcp_tw_reuse 允许复用处于 TIME_WAIT 状态的 socket,前提是时间戳严格递增。但在大量客户端共用一个出口 IP(如 Kubernetes Node、云 NAT 网关)时,不同连接的时间戳可能碰撞,导致 RST 或连接失败。
实操建议:
- 只在明确可控的客户端侧启用(如单机压测脚本),服务端禁用更安全
- 替代方案优先调小
net.ipv4.tcp_fin_timeout(默认 60s)至 30s,或增大net.ipv4.ip_local_port_range扩展可用端口 - 验证是否真有瓶颈:用
ss -tan state time-wait | wc -l统计数量,>3w 才值得动参数,别一上来就改
net.ipv4.tcp_congestion_control 切换后未生效
改完 net.ipv4.tcp_congestion_control 后,新连接仍走旧算法,常见原因是:没有重启已有连接,或未加载对应内核模块(如 bbr 需 lsmod | grep bbr 确认)。
实操建议:
- 查看当前算法:
sysctl net.ipv4.tcp_congestion_control - 加载模块(以 bbr 为例):
modprobe tcp_bbr,再执行sysctl -w net.ipv4.tcp_congestion_control=bbr - 必须重启测试连接(比如 curl 新请求、telnet 新建 TCP 流),已建立连接不受影响;容器环境注意 init 进程是否继承了父级 TCP 设置
调参不是开箱即用的魔法开关,每个值背后都绑着协议逻辑、硬件延迟、网络拓扑和应用行为。改之前先抓包看三次握手、RTT 分布、重传率,比盲目调 net.ipv4.tcp_rmem 有用得多。










