网络优化基础: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,光握手就耗掉半秒。
优化策略:
- 启用 TCP 快速打开(TFO):允许在 SYN 包中携带数据,减少一次 RTT
- TLS 1.3 升级:相比 TLS 1.2,握手从 2-RTT 降到 1-RTT,甚至 0-RTT
- 会话复用:缓存 Session ID 或 Session Ticket,避免重复握手
- 调整 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 个关键域名。
六、实战建议:怎么选?怎么配?
说了这么多,落地才是关键。我一般这样建议团队:
- 能上 HTTP/2 就上 HTTP/2:现在主流服务器(Nginx、Apache)和浏览器都支持,配置也不复杂。迁移后记得去掉域名分片和雪碧图。
- HTTP/3 看场景:如果你的用户群体在弱网环境多(移动端、海外),或者对首屏速度要求极高,值得上。但要注意,有些防火墙会拦截 UDP 包。
- TLS 1.3 必须开:这是性价比最高的优化,改个配置就能省一个 RTT。
- DNS 预解析做减法:只对关键域名做,别贪多。
最后说一句,网络优化不是一锤子买卖。你想想看,用户的网络环境千差万别,今天 5G 明天 2G,所以最好在代码里做降级处理——支持 HTTP/3 就用,不支持就回退到 HTTP/2 或 HTTP/1.1。嗯,这才是靠谱的做法。