SACK 为什么能加速恢复
SACK(选择性确认,RFC 2018)让接收方在一个确认里报告自己已经收到的不连续区间,发送方据此只重传真正缺失的部分。没有 SACK 时只能靠累计确认,一次丢包就要从缺口开始整段重发。抓包里 SACK 选项的左右边界直接画出已接收范围,边界之间的空洞就是要重传的对象,所以开启 SACK 的连接恢复节奏明显更快。
基本信息
| 关键字段 | tcp.options.sack_le、tcp.options.sack_re、tcp.options.sack |
|---|---|
| 能力协商 | SYN 中携带 SACK Permitted 选项 |
| 相关机制 | RFC 6675 的快速恢复与丢失检测 |
| 观察指标 | 恢复耗时、重传包数、重复确认数量 |
典型使用场景
- 对比同一路径上开启与关闭 SACK 的恢复效率
- 排查中间设备剥离 TCP 选项造成的性能回退
- 多次丢包场景下比较恢复速度差异
- 为传输优化(内核参数、负载均衡设置)提供抓包证据
- 统计一次故障中实际重传了多少数据
观察与统计
观察与统计
tshark -r a.pcap -Y "tcp.options.sack" -T fields -e frame.number -e tcp.stream -e tcp.options.sack_le -e tcp.options.sack_re
# 左右边界构成已接收区间,区间之间的空洞就是要重传的数据
tshark -r a.pcap -Y "tcp.flags.syn==1 && tcp.options.sack_perm" -T fields -e tcp.stream
# 确认握手时是否协商了 SACK 能力,没有就谈不上收益
tshark -r a.pcap -Y "tcp.analysis.retransmission" -T fields -e tcp.stream | sort | uniq -c
# 按流统计重传次数,用于比较优化前后的差异观察项读法
| 观察项 | 含义 | 判读 |
|---|---|---|
| tcp.options.sack_le / sack_re | 已接收区间的左右边界 | 边界之间的空洞即缺失数据 |
| tcp.options.sack_perm | SACK 能力协商 | 未协商则 SACK 不生效 |
| 重传包数与恢复耗时 | 恢复成本 | 开启 SACK 后应明显下降 |
| 重复确认数量 | 触发恢复的信号 | 数量多说明缺口较集中 |
丢包越多,SACK 的优势越明显。单次丢包时累计确认加重传也能较快恢复;出现连续多个空洞时,没有 SACK 就要多等几个往返,这在长肥管道上代价很大。
部分中间设备会剥离或改写 TCP 选项,老式防火墙与带 TCP 代理的负载均衡是常见来源。表现为 SYN 里看不到 SACK 选项、性能回退但没有任何报错,抓两端的握手帧对比就能确认。
排查顺序
- 先在握手帧确认双方是否协商了 SACK 能力
- 再统计丢包时段的重传次数与恢复耗时
- 与关闭 SACK 的基线对照,量化差异
- 检查路径上是否有设备改写 TCP 选项,两端抓包比对
- 确认内核与负载均衡配置是否一致,避免同集群内行为不统一