网络请求开销,到底花在哪儿?

做 SDK 接入优化,第一件事就是得搞清楚:一次网络请求,钱都花在哪了。

很多人一上来就调参数、改协议,结果连基础开销都没摸清楚。我见过不少团队,花了大力气优化业务逻辑,结果发现最耗时的反而是网络握手那几步。说白了,地基没打好,上面怎么盖都白搭。

HTTP 协议:远比你想象的重

咱们天天跟 HTTP 打交道,但你真的算过它的开销吗?

先回顾一下 HTTP 的几个版本,看看差别有多大:

版本 连接方式 复用能力 典型延迟(理想) 我见过的坑
HTTP/1.0 短连接,一次请求一个 TCP 无 2×RTT + 传输 请求多时,光握手就占了 60% 时间
HTTP/1.1 持久连接,支持 keep-alive 队列串行 1×RTT + 传输 队头阻塞严重,一个慢请求卡住后面所有
HTTP/2 多路复用,单一 TCP 连接 并行流 1×RTT + 传输 TCP 丢包时,所有流一起受影响
HTTP/3 基于 QUIC,UDP 传输 独立流,无队头阻塞 0-RTT(首次除外) 有些老旧中间件不支持,得做降级

嗯,这里要注意。很多人以为用了 HTTP/2 就万事大吉了。我记得有个项目,团队兴冲冲上了 HTTP/2,结果发现某些弱网环境下,延迟反而比 HTTP/1.1 还高。为什么?因为 TCP 丢包重传会阻塞所有流——你想想看,一个视频流丢包,把旁边的信令请求也卡住了。

核心认知:HTTP 协议本身不产生延迟,但它对底层传输机制的使用方式,决定了延迟的上限。

TCP 三次握手:1.5 个 RTT 的沉默成本

每次建立新连接,TCP 都要来一次「三次握手」。过程不复杂,但开销实实在在:

  1. 客户端 → 服务器:SYN(同步序列号)
  2. 服务器 → 客户端:SYN + ACK(确认并同步)
  3. 客户端 → 服务器:ACK(确认建立)

整个过程,客户端需要等 1.5 个 RTT 才能开始发数据。你算算,如果 RTT 是 100ms,那就是 150ms 的纯开销,还没发任何业务数据呢。

我早年间做过一个广告 SDK,每次启动时要拉取配置。当时没注意,每次请求都新建 TCP 连接,结果用户打开 App 后,光握手就用了 300ms 以上——用户早划走了。后来我把连接池加上,才把延迟压下来。

曾经我踩过一个坑:以为 keep-alive 能解决一切,但没配超时时间。结果连接池里全是半死不活的连接,新请求反而要等超时才能重建。那叫一个痛苦。

TLS 握手:雪上加霜的加密开销

现在 HTTPS 基本是标配了。但你有没有算过,TLS 握手比 TCP 握手要重多少?

以经典的 TLS 1.2 完整握手为例:

  • TCP 握手:1.5 RTT
  • TLS 握手:2 RTT(ClientHello → ServerHello → 证书 → 密钥交换)
  • 合计:3.5 RTT 之后,才能发第一个 HTTP 请求

这还没完,TLS 的证书验证也在握手阶段。我曾经抓包分析过一个海外服务,证书链有 5 级,光把证书数据传完就花了 200ms 的传输时间。

TLS 版本 握手 RTT 计算开销 恢复会话 RTT 我个人的建议
TLS 1.2 2 RTT 高(尤其 DH 密钥交换) 1 RTT(Session ID/票证) 尽量复用会话,减少完整握手
TLS 1.3 1 RTT 较低 0 RTT(Early Data) 强烈推荐升级,但 0-RTT 有重放风险

一个小技巧:在 App 启动预热阶段,可以提前做一次 TLS 握手,把 Session Ticket 缓存下来。这样真正发请求时,省掉一个 RTT。

三种协议层综合开销对比

我把上面这些加在一起,算了一笔账。假设 RTT = 80ms,情况如下:

  • HTTP + TCP:1.5 RTT = 120ms
  • HTTPS + TCP + TLS 1.2:3.5 RTT = 280ms
  • HTTPS + TCP + TLS 1.3:2.5 RTT = 200ms
  • HTTPS + QUIC (HTTP/3):首次 1 RTT = 80ms

看清了吗?一次 HTTPS 请求,光握手就占了 200ms 以上。如果你的 SDK 里要发生多次请求,这个开销还会累积。

为什么会这样?说白了,TCP 和 TLS 的设计初衷是「可靠」和「安全」,不是「快」。在移动端和弱网环境下,这些设计就显得特别笨重。我们做优化,就是要在这两样东西之间找到平衡点。

给本章画个重点:

  1. 每个 RTT 都是真金白银的延迟,能省则省
  2. TCP 三次握手是最基础的沉默成本,用连接池来减少
  3. TLS 握手是最大的额外开销,优先用 TLS 1.3 和会话复用
  4. 别盲目升级协议,要结合你的实际网络环境和业务场景
一次 SDK 网络请求的延迟分解 一次 HTTPS 请求的延迟构成(RTT = 80ms) 应用层:SDK 发起 HTTP 请求 传输层:TCP 三次握手 SYN → SYN+ACK → ACK(1.5 RTT = 120ms) 安全层:TLS 握手 ClientHello → ServerHello + 证书 → 密钥交换(2 RTT = 160ms) 应用层:HTTP 请求发送 + 响应接收(1 RTT = 80ms) 总耗时 ≈ 3.5 RTT = 280ms(未优化) 其中 80% 时间在握手,仅 20% 在传数据 优化切入点: 连接池 / TLS 1.3 / 会话复用 / QUIC