网络优化基础:HTTP/1.1 vs HTTP/2 vs HTTP/3、TCP与TLS握手优化、DNS预解析

聊到前端性能优化,网络层面是绕不开的第一道坎。我个人习惯把网络优化比作「修路」——路宽了、红绿灯少了、收费站效率高了,数据自然跑得快。今天咱们就聊聊这三条「高速公路」:HTTP/1.1、HTTP/2 和 HTTP/3,以及怎么让 TCP/TLS 握手少磨蹭,DNS 预解析提前指路。

一、HTTP/1.1:老路虽稳,但堵车严重

HTTP/1.1 诞生于 1997 年,说实话,它当年设计的时候压根没想过今天的网页会这么「胖」。一个页面动辄几百个请求,JS、CSS、图片、字体……全挤在同一条连接上。

核心痛点:队头阻塞(Head-of-Line Blocking)

什么意思呢?就是同一连接上,请求必须排队。前一个请求没响应,后面的就得等着。我在项目中遇到过这样一个场景:一个页面加载了 80 多张商品图,HTTP/1.1 下浏览器最多开 6 个连接,每个连接里请求还得排队。结果首屏加载花了 8 秒多,用户早跑了。

HTTP/1.1 的典型优化手段:

  • 域名分片(Domain Sharding):把资源分散到多个域名,变相增加连接数
  • 雪碧图(CSS Sprites):把小图标合成一张大图,减少请求
  • 资源内联(Inline):把小的 CSS/JS 直接塞进 HTML

但这些说白了都是「打补丁」。你想想看,为了绕过协议本身的限制,前端工程师得做多少额外工作?

二、HTTP/2:多路复用,路宽了

HTTP/2 在 2015 年正式标准化,核心改进就是 多路复用。它允许在同一个 TCP 连接上同时发送多个请求和响应,互不干扰。

为什么会这样?因为 HTTP/2 引入了「二进制分帧层」。数据被拆成更小的帧,每个帧带上流 ID,到了服务端再重新组装。这样一来,请求 A 和请求 B 可以「并排走」,谁也不用等谁。

我个人的经验: 把项目从 HTTP/1.1 迁移到 HTTP/2 后,首屏加载时间直接降了 40%。而且之前做的那些域名分片、雪碧图,反而成了累赘——因为 HTTP/2 下,多个连接反而会增加开销,雪碧图也破坏了缓存粒度。

HTTP/2 的关键特性:

  • 多路复用:一个连接并发处理多个请求
  • 头部压缩(HPACK):减少重复的 Header 开销
  • 服务端推送(Server Push):服务端可以主动把资源推给客户端
  • 二进制协议:比 HTTP/1.1 的文本协议解析更快

注意: HTTP/2 虽然解决了应用层的队头阻塞,但 TCP 层的队头阻塞依然存在。因为 TCP 是可靠传输,丢包时后续数据必须等重传。这就是 HTTP/3 要解决的问题。

三、HTTP/3:QUIC 协议,彻底告别队头阻塞

HTTP/3 基于 QUIC 协议,而 QUIC 又跑在 UDP 上。说白了,它把 TCP 的可靠性 + TLS 的安全性 + UDP 的低延迟,揉在了一起。

HTTP/3 的核心优势:

  • 0-RTT 连接:之前连过的服务器,第二次连接几乎零延迟
  • 无队头阻塞:一个流丢包不影响其他流
  • 连接迁移:切换网络(比如从 WiFi 切到 4G)连接不中断

我记得有一次帮客户优化海外站点的加载速度。他们的用户主要在东南亚,网络质量参差不齐。切换到 HTTP/3 后,弱网环境下的加载成功率提升了 30% 以上。因为 QUIC 的 0-RTT 和连接迁移特性,在丢包率高的情况下优势特别明显。

三种协议对比:

特性 HTTP/1.1 HTTP/2 HTTP/3
传输层 TCP TCP QUIC (UDP)
队头阻塞 应用层 + TCP 层 仅 TCP 层
连接建立 3 次握手 3 次握手 0-RTT / 1-RTT
头部压缩 HPACK QPACK
多路复用 不支持 支持 支持
连接迁移 不支持 不支持 支持

四、TCP 与 TLS 握手优化:别让握手拖慢你

不管用 HTTP/1.1 还是 HTTP/2,TCP 的三次握手和 TLS 的加密握手都是绕不开的「过路费」。一个 HTTPS 请求,光握手就要 2-3 个 RTT(往返时间)。如果用户在美国,服务器在中国,一个 RTT 就是 150ms,光握手就耗掉半秒。

优化策略:

  1. 启用 TCP 快速打开(TFO):允许在 SYN 包中携带数据,减少一次 RTT
  2. TLS 1.3 升级:相比 TLS 1.2,握手从 2-RTT 降到 1-RTT,甚至 0-RTT
  3. 会话复用:缓存 Session ID 或 Session Ticket,避免重复握手
  4. 调整 TCP 初始拥塞窗口:Linux 默认 10 个 MSS,可以适当调大,让慢启动更快

我曾经踩过一个坑: 某次上线后,发现部分用户连接特别慢。排查了半天,发现是 CDN 节点没有开启 TLS 1.3,导致握手多了一轮。升级后,首字节时间(TTFB)直接降了 200ms。嗯,这里要注意,CDN 配置也要同步检查。

五、DNS 预解析:提前问路,少走弯路

DNS 解析虽然看起来不起眼,但每个域名都要查一次。一个页面如果引用了 10 个不同域名的资源,DNS 查询就得 10 次。每次几十到几百毫秒,加起来也不少。

DNS 预解析(DNS Prefetch) 就是让浏览器提前去查 DNS,等真正需要加载资源时,IP 地址已经准备好了。

实现方式:

<!-- 在 HTML 的 <head> 中添加 -->
<link rel="dns-prefetch" href="//cdn.example.com">
<link rel="dns-prefetch" href="//api.example.com">

<!-- 更激进的预连接(Preconnect),包含 DNS + TCP + TLS -->
<link rel="preconnect" href="//cdn.example.com">

什么时候用?

  • 第三方资源(CDN、字体、统计脚本)
  • 用户即将点击的链接(比如搜索结果页的下一页)
  • 首屏渲染必需的跨域资源

注意: 不要滥用。预解析会消耗浏览器资源,如果页面有 50 个域名全预解析,反而会拖慢首屏。我建议只预解析首屏必需的 3-5 个关键域名。

六、实战建议:怎么选?怎么配?

说了这么多,落地才是关键。我一般这样建议团队:

  1. 能上 HTTP/2 就上 HTTP/2:现在主流服务器(Nginx、Apache)和浏览器都支持,配置也不复杂。迁移后记得去掉域名分片和雪碧图。
  2. HTTP/3 看场景:如果你的用户群体在弱网环境多(移动端、海外),或者对首屏速度要求极高,值得上。但要注意,有些防火墙会拦截 UDP 包。
  3. TLS 1.3 必须开:这是性价比最高的优化,改个配置就能省一个 RTT。
  4. DNS 预解析做减法:只对关键域名做,别贪多。

最后说一句,网络优化不是一锤子买卖。你想想看,用户的网络环境千差万别,今天 5G 明天 2G,所以最好在代码里做降级处理——支持 HTTP/3 就用,不支持就回退到 HTTP/2 或 HTTP/1.1。嗯,这才是靠谱的做法。