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 只应作为兼容性排查的临时手段,完成后要恢复默认。长期关闭会让高带宽高延迟链路上的丢包恢复代价显著上升,吞吐下降幅度可能达到数倍。