本文是对《延迟增加了多少?》一文的答案和分析。
总延迟应该是 900ms 左右。
Ping 的延迟指的是 RTT, Round Trip Time. 即一个包发过去,对方发一个包回来,总延迟是 200ms。一种误解是认为 ping 测得的延迟是 200ms,所以一个请求发过去是 200ms,响应发回来是 200ms,总延迟是 400ms。如果仔细想一想的话,我们在发送端测量延迟的时候,没有办法只测量一个包从发送端达到接收端的延迟。除非是让接收端在回复的时候记录收到包的时间?但是发送端和接收端的时钟可能不一致,如果精确测量的话,协议上就要依赖不同的机器时钟对齐。直接让总时间除以 2?这也意义不大,因为包去和回的路线不一定一样,延迟也不一定是一半一半。所以我们在讨论延迟的时候,都是默认 RTT。
TCP 握手的延迟是 1 个 RTT,即 200ms。这里也有很多人会有一个误解,就是认为「TCP 是三次握手,所以握手带来的延迟是 1.5 RTT」。这个误解是因为教科书的 TCP 序列图太迷惑了,看起来像是握手需要发送 3 个包,之后才能发送数据。实际上,在握手阶段,第三个包 ACK 发出之后,发送端直接开始发送数据。即,客户端发送 SYN 建立握手,收到 SYN+ACK,消耗了 1 个 RTT;发送端随即发送 ACK,然后直接进入数据发送阶段,开始发送数据。所以握手阶段第三个 ACK 包是不会带来延迟的。
上文题目提到,请求的大小是 16KiB,这里经常出现的误解是:「一个 Frame 的 MTU 是 1500bytes,减去 20 bytes IP header 和 20 bytes TCP header,一个包携带的实际数据是 1460 bytes,所以 16KiB 请求传输完成是 16KiB/1460 bytes 个 RTT。」这也是被教科书常用的序列图迷惑了,TCP 传输中,发送端并不是发送一个包,等待 ACK,发送下一个包……而是直接传输很多包,接收端可以直接用一个 ACK 去 ACK 多个包。发送端是「一组包一组包地发送」,而不是「一个包一个包地发送」。
那么一下子可以发送多少个包呢?发送端可以一下子把 16KiB 的数据都发送完吗?这里涉及到 TCP 的拥塞控制了。为了避免过载接收端和中间链路上的路由器等设备,TCP 发送端发送出去但是未确认的数据会保持在接收端窗口 (rwnd)和拥塞控制窗口之内 (cwnd)。接收端的窗口一般不是瓶颈,所以这里忽略不讨论。cwnd 在 Linux 的初始值是 10,即 TCP 连接建立之后,会一下子发送 10 个 MSS 的数据,即 1460 bytes * 10 大约是 14.6KiB 的数据。然后会等待接收端发送回来 ACK,再开始下一轮数据的发送,并且逐渐增大 cwnd。对于响应,同理,这时候服务 B 的服务器变成了发送端,也是需要发送两轮数据。更详细的解释可以阅读这篇:《TCP 拥塞控制对数据延迟的影响》。
最后,来到了四次挥手。这里的误解是 TCP 断开连接 4 次挥手需要花费 2 个 RTT。实际上,断开连接的过程是不产生耗时的,因为在 TCP 断开连接之前,应用的请求已经发送完成,响应也已经收到,kernel 已经将收到的数据送给了用户态,用户态的程序已经继续运行了。即使应用调用 close(), 也是直接返回,kernel 再慢慢处理关闭连接的过程。所以断开连接是 kernel 来做的「收尾工作」,不会贡献请求处理的延迟。
综上,总结一下,实际耗时是 900ms,其中:
- TCP 建立连接需要 1 个 RTT;
- 如果是 HTTP 请求很小,响应也很小,那么请求和响应需要耗费 1 个 RTT;
- 但是 HTTP 请求很大,因为 cwnd 的限制,需要额外耗费 1 个 RTT 来传输;
- 同理,响应也很大,也需要额外花费 1 个 RTT;
- 服务端程序处理需要花费 100ms,保持不变;
最后是 200ms * 4 个 RTT + 100ms = 900ms;
再留一个问题给读者:你知道应该如何优化,让这个请求耗费的延迟最小吗?(分析一下最小延迟是多少,一个 RTT 用来传输数据是比不可少的,服务端的 100ms 也无法节省,所以最小延迟是 300ms,如何从 900ms 优化到 300ms 呢?)
==抓包破案录==
这篇文章是抓包破案录系列文章(之前叫做《计算机网络实用技术》,后来改名了)中的一篇,这个系列正在连载中,我计划用这个系列的文章来分享一些网络抓包分析的实用技术。这些文章都是总结了我的工作经历中遇到的问题,经过精心构造和编写,每个文件附带抓包文件,通过实战来学习网络抓包与分析。
如果本文对您有帮助,欢迎扫博客右侧二维码打赏支持,正是订阅者的支持,让我公开写这个系列成为可能,感谢!
如果您正在阅读的是题目类的文章,这个目录内容正好用来隔离其他读者的评论。读完题目可以稍作暂停,进行思考,继续向下滑动,可能会被其他的读者剧透答案。
没有链接的目录还没有写完,敬请期待……
- 序章
- 抓包技术以及技巧
- 理解网络的分层模型
- 数据是如何路由的
- 网络问题排查的思路和技巧
- 不可以用路由器?(答案和解析)
- 网工闯了什么祸?(答案和解析,阅读加餐!)
- 重新认识 TCP 的握手和挥手(答案和解析)
- 3.5 秒初始延迟问题 (答案和解析)
- 网络断断续续…… (答案和解析)
- 延迟增加了多少?(答案和解析)
- 压测的时候 QPS 为什么上不去?(答案和解析)
- TCP 下载速度为什么这么慢?(答案和解析)
- 请求为什么超时了?(答案和解析)
- 0.01% 的概率超时问题 (答案和解析)
- 后记:学习网络的一点经验分享
与本博客的其他页面不同,本页面使用 署名-非商业性使用-禁止演绎 4.0 国际 协议。





























