启用 TCP SACK (Selective Acknowledgement) 功能, 因此在大量丢包的时候不需要每个重传包都确认一次, 也就不怕延迟确认的影响了。

    • 由于启用了 SACK, 所以服务器可以在 4 个 “Ack 3” 中告知客户端哪些包已经收到了
    • 因为客户端已经知道哪些包丢了, 哪些包已经收到, 所以它可以一口气完成重传

    image.png

    • 661857-663035 已经送达
    • 656925-661856 丢失

    image.png

    • 重传的数据包总长度: 4932

    image.png

    启用 SACK 其实比关闭延迟确认更高效.

    从本质上看, 延迟确认之所以会在大量重传时影响性能, 是因为它在该场景下会多次出现 (甚至因为延迟太久而导致超时重传).

    还有什么场景会导致延迟确认多次出现呢?

    • TCP 窗口极小的情况

    图 4 演示了服务器接收窗口只有 2920 字节 (相当于两个 MSS), 且关闭了延迟确认时的场景:

    • 客户端每发两个包就会耗光窗口, 所以不得不停下来等待服务器的确认
    • 假如这时候在服务器上启用了延迟确认, 那 29 号和 30 号之间、32 号与 33 号之间……以及 38 号和 39 号之间都需要多等待 200 毫秒, 意味着传输效率会下降数百倍

    image.png

    如何在 Wireshark 中发现延迟确认,并计算它所带来的影响:

    • tcp.analysis.ack_rtt > 0.2 and tcp.len==0