Linux TCP/IP 参数调优方法

1次阅读

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

Linux TCP/IP 参数调优方法

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 后,新连接仍走旧算法,常见原因是:没有重启已有连接,或未加载对应内核模块(如 bbrlsmod | 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 有用得多。

text=ZqhQzanResources