首页/系统/Linux 内核与性能调优速查/net.ipv4.tcp_sack 选择性确认
网络栈调优98 条

net.ipv4.tcp_sack 选择性确认

SACK 让接收方通告缺口以外的已收数据,重传只补丢失段;默认开启,是高速链路丢包恢复的基础机制。

SACK 是什么

net.ipv4.tcp_sack 控制是否启用 TCP 选择性确认(SACK,RFC 2018):接收方用 SACK 选项告知自己已收到哪些不连续的数据块,发送方据此只重传真正丢失的段,而不必把丢失点之后的全部数据重发。它是高带宽高延迟链路丢包恢复的基础机制,默认开启;一旦关闭,丢包恢复退化,长肥管道的吞吐会明显下降。

基本信息

参数net.ipv4.tcp_sack
默认值1(开启)
相关参数net.ipv4.tcp_dsack(重复 SACK,默认开启)
观测方式ss -ti 输出中的 sacks、retrans 计数
持久化写入 /etc/sysctl.d/*.conf 后 sysctl --system
生效前提两端都启用,且中间设备不破坏 TCP 选项

典型使用场景

  • 跨地域链路丢包率偏高时,确认 SACK 是否真的在生效(sacks 计数增长)
  • 排查与老旧防火墙、负载均衡设备的兼容性问题时临时关闭并验证
  • 解释重传行为与吞吐下降:理解为何恢复代价差异巨大
  • 与 tcp_dsack 一起排查重复数据包与伪重传
  • 为高带宽时延积链路的调优提供前提检查项

查看与验证

查看与验证
sysctl net.ipv4.tcp_sack net.ipv4.tcp_dsack  # 查看两个开关的当前值
ss -tin dst :443  # 关注 sacks:、retrans:、cwnd:、rtt: 四类字段
ss -tin | grep -o 'sacks:[0-9]*' | sort | uniq -c | head  # 统计有多少连接在用 SACK
sudo tcpdump -i eth0 -nn port 443 -c 20 -vv  # 抓包观察两端报文中的 SACK 选项
printf 'net.ipv4.tcp_sack = 1\n' > /etc/sysctl.d/90-sack.conf  # 排查后恢复为开启
sysctl --system  # 重新加载并复核回显

观测项读法

观测项含义判读要点
sacks该连接使用 SACK 的次数增长说明机制在工作
retrans重传的段数异常偏高要查丢包位置与中间设备
cwnd拥塞窗口过小说明链路受限或丢包
rtt往返时间估计用于判断链路时延量级
SACK 需要两端都启用、且中间设备不改写 TCP 选项才能完整工作。出现难以解释的异常重传时,抓包对比两端报文,确认 SACK 信息是否被改写或丢弃。
关闭 SACK 只应作为兼容性排查的临时手段,完成后要恢复默认。长期关闭会让高带宽高延迟链路上的丢包恢复代价显著上升,吞吐下降幅度可能达到数倍。

易错点

  • 为「优化」而关闭 SACK:高带宽高延迟链路的吞吐会明显下降,属于典型的反向调优
  • 中间设备改写 SACK 选项导致异常重传:只在一端排查会找不到原因,需要两端抓包对比
  • 只看开关不看计数:参数为 1 不等于实际生效,要用 ss -ti 的 sacks 计数确认
  • 把 SACK 与 DSACK 混为一谈:两者用途不同,排查重复数据包时才需要关注后者
  • 排查后忘记恢复:sysctl -w 的临时改动在重启后回退,容易造成「环境不一致」的困惑

数据来源与参考

  • Linux 内核 Documentation/networking/
  • man-pages tcp(7)
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌