前言
做前端架构的人要不要懂 HTTP?我的回答是 要——不是去读 RFC 2616,而是建立”一次 HTTP 请求到底怎么走完”的工程直觉。原因有三:
- 首屏优化的天花板是网络层。HTML / CSS / JS 怎么优化都压不过 TTFB;HTTP/3 vs HTTP/1.1 在弱网下差距能到 300ms。
- 缓存策略决定二次访问速度。Cookie / Cache-Control / ETag / Service Worker 这些机制相互交织,配错一个就是”开发 OK 生产炸”。
- CDN / 边缘计算选型不靠直觉。Cloudflare / Fastly / Akamai 的协议支持差异巨大;HTTP/3 启用需不需要等运维、需不需要重写代码,依赖对协议栈的理解。
这一篇是『前端架构修仙路』的第 4 篇。我跳过 RFC 细节(不解释每个 header 的语法),用架构图 + 真实数据 + 选型决策表,把 HTTP 演进、TLS 握手、HTTP/2 多路复用、HTTP/3 QUIC、浏览器缓存讲透。下一篇聊前端安全(XSS / CSRF / CSP / SRI)。
一、HTTP 演进:从 1.0 到 3 的本质变化
1.1 演进时间线
1.2 HTTP/1.1 的核心问题:队头阻塞
HTTP/1.1 引入了 Keep-Alive(连接复用)和 管道(pipelining),但实际收益远低于理论。原因:
- 请求-响应必须严格按序——客户端必须按顺序发出请求,按顺序收到响应。如果请求 1 的响应慢,请求 2-10 都要等。
- 连接数限制——浏览器对同一域名并发连接数有限制(Chrome 6 个),多出的请求排队。
- 队头阻塞(Head-of-Line Blocking)——TCP 层丢包会重传整个窗口,所有在飞的 HTTP 请求都卡住。
生产案例:顺丰 ERP 首页要加载 12 个 JS chunk(vendor、polyfill、4 个业务模块、路由、状态管理、监控、统计、SDK),HTTP/1.1 下需要 6 + 6 = 12 个 RTT(两批),单次首屏 = 6 × RTT。
二、HTTP/2:二进制分帧与多路复用
HTTP/2 是 2015 年发布的协议大版本,解决了 HTTP/1.1 的核心问题。
2.1 核心机制:二进制分帧
HTTP/2 把 HTTP 消息(请求 / 响应)拆成更小的二进制帧,每帧带 stream ID 和 type。同一 TCP 连接上可同时跑多个 stream。
TCP 连接 ── stream 1 (主 HTML)
├── stream 3 (CSS)
├── stream 5 (JS chunk 1)
├── stream 7 (JS chunk 2)
└── stream 9 (image)
带来的好处:
- 一个 TCP 连接就够了(解决 HTTP/1.1 的 6 个并发限制)
- 多路复用,没有 HTTP 层队头阻塞
- 二进制帧解析快于文本协议
2.2 头部压缩 HPACK
HTTP/2 用 HPACK 算法压缩 header:
- 客户端和服务端维护一张”header 字段表”
- 重复 header 用索引号代替(节省字节)
- Huffman 编码压缩字符串
生产数据:一个完整 HTTP 请求 header 大约 800 字节,HPACK 后能压到 30-50 字节。在 4G 弱网下,每个请求节省 ≈ 50ms。
2.3 HTTP/2 的暗坑:TCP 层队头阻塞
HTTP/2 解决了 HTTP 层队头阻塞,但没解决 TCP 层队头阻塞。TCP 是按序交付的字节流:
TCP 窗口: [frame1 stream A] [frame2 stream B] [frame3 stream A]
↓ 如果 frame2 丢失
↓ TCP 重传
↓ frame1 和 frame3 都得等
生产案例:跨太平洋链路丢包率 1-3%,HTTP/2 在这种链路下反而比 HTTP/1.1 慢——因为 1 个 TCP 包丢失会卡住整连接的所有流。这正是 HTTP/3 要解决的痛点。
2.4 Server Push(已废)
HTTP/2 引入了 Server Push——服务端主动推送资源(不需要客户端请求)。Chrome 107+ 已经移除 Server Push(官方说明),原因是缓存命中率低、协议复杂度高。生产不要用。
三、HTTP/3:基于 QUIC 的真正并行
HTTP/3 是 2022 年正式发布(IETF RFC 9114),用 QUIC 替代 TCP 作为传输层。核心突破:UDP 之上的可靠传输。
3.1 QUIC 为什么用 UDP
TCP 的核心问题:内核态实现,协议升级需要操作系统更新(几十年才推进一点点)。QUIC 把传输层逻辑搬到 用户态(在浏览器 / 应用进程里实现),协议升级只需要更新浏览器。
3.2 QUIC 解决了 HTTP/2 解决不了的问题
| 问题 | HTTP/2 (TCP) | HTTP/3 (QUIC) |
|---|---|---|
| 队头阻塞 | TCP 层丢包卡所有流 | 每个 stream 独立,丢一不卡多 |
| 握手延迟 | TCP 三次 + TLS 三次 ≈ 2-3 RTT | 1-RTT 握手(QUIC 内置 TLS 1.3) |
| 连接迁移 | WiFi → 4G IP 变 → 连接重置 | Connection ID 标识,IP 变不影响连接 |
| 拥塞控制 | 内核级,跨平台不一致 | 应用层,可差异化(BBR / Cubic) |
生产数据:某海外业务从 HTTP/1.1 升 HTTP/3 后,高丢包率(5%)链路下首屏时间从 4.5s 降到 2.8s(节省 38%)。
3.3 HTTP/3 部署现状(2024)
| 浏览器 | 支持版本 | 备注 |
|---|---|---|
| Chrome | 87+ | 默认开启 |
| Firefox | 88+ | 默认开启 |
| Safari | 14+ | 默认开启 |
| Edge | 87+ | 默认开启 |
服务端支持:Cloudflare / Fastly / Nginx 1.25+(含 quiche 库)/ Caddy / Envoy / HAProxy 2.3+。启用只需配好证书和 UDP 443 端口。
CDN 现状:
- Cloudflare 默认开启 HTTP/3
- Fastly 可配置开启
- AWS CloudFront 支持 HTTP/3(2023+)
顺丰 ERP 升级到 Cloudflare + HTTP/3 后,TTFB 从 800ms 降到 80ms(4.2s→1.8s 首屏优化的第一步)。
四、TLS 1.3:让 HTTPS 不再慢
4.1 TLS 1.2 vs 1.3 握手对比
关键改进:
- 1-RTT 握手(首次连接)vs TLS 1.2 的 2-RTT
- 0-RTT 握手(会话恢复)——客户端在第一帧就发加密数据
- 移除了不安全的加密套件(RC4、SHA-1、DES)
- 完全前向保密(Perfect Forward Secrecy)强制
4.2 OCSP Stapling:消除证书验证的额外延迟
传统 TLS 验证需要客户端查 OCSP(证书吊销状态),通常多 1 个 RTT。OCSP Stapling让服务端提前查 OCSP 并”装订”到 TLS 握手,客户端无需额外请求。
生产配置:Cloudflare 默认开启 OCSP Stapling;自建 Nginx 用 ssl_stapling on; ssl_stapling_verify on;。
4.3 HSTS:强制 HTTPS
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
架构师必加:一旦上了 HTTPS,就给所有响应加 HSTS 头。生产案例:某中后台系统最初只对 /api 强制 HTTPS,但 /static 还是 HTTP,被中间人篡改后塞了广告。加 HSTS 后浏览器强制走 HTTPS,问题根治。
五、浏览器缓存策略:Cache-Control / ETag / Service Worker
5.1 缓存层级
匹配优先级:内存缓存 → Service Worker → HTTP 缓存 → CDN 缓存 → 源站。架构师要点:每一层都能省下一段 RTT。
5.2 Cache-Control 指令速查
# 静态资源(CSS / JS / 图片 / 字体)
Cache-Control: public, max-age=31536000, immutable
# 一年缓存,且不可变(带 hash 的资源)
# HTML 主文档
Cache-Control: no-cache, must-revalidate
# 每次都要向服务端验证(304 协商)
# 私有数据(用户相关)
Cache-Control: private, no-store
# 不缓存任何地方
生产规则:
| 资源类型 | 推荐 Cache-Control |
|---|---|
带 hash 的 JS / CSS(如 app.abc123.js) | public, max-age=31536000, immutable |
| 普通 HTML | no-cache, must-revalidate + ETag |
| API 响应(用户相关) | private, no-store |
| 公开 API 响应 | public, s-maxage=300, max-age=60 |
| 图片(不可变) | public, max-age=31536000, immutable |
| 字体 | public, max-age=31536000, immutable |
5.3 ETag 与 304 协商
ETag(Entity Tag) 是资源的”指纹”,服务端给每个响应生成。客户端下次请求带 If-None-Match: <etag>,服务端比较:
- 资源未变 → 返回
304 Not Modified,无 body - 资源变了 → 返回
200 OK+ 新内容
生产数据:300 KB 的 JS bundle,每次都下载 = 800ms。ETag 命中后 304 通常 < 50ms。所以 hash bundle 一定要配 ETag。
5.4 Service Worker 缓存策略
// stale-while-revalidate 模式:先返回缓存,后台更新
self.addEventListener('fetch', (e) => {
e.respondWith(
caches.open('v1').then(async (cache) => {
const cached = await cache.match(e.request);
const fetched = fetch(e.request).then((res) => {
cache.put(e.request, res.clone());
return res;
}).catch(() => cached);
return cached || fetched; // 缓存优先,网络后台更新
}),
);
});
stale-while-revalidate 是 Service Worker 最常用的策略:用户秒开(缓存),后台拉新(更新),下次访问拿最新。
六、CDN 与边缘计算选型
6.1 CDN 的核心价值
CDN(Content Delivery Network)的核心是把内容推到离用户最近的边缘节点:
未用 CDN: 用户 → 北京源站 = 200ms
用 CDN: 用户 → 边缘节点(就近) = 20ms
首屏 200ms 节省对 LCP 影响巨大。
6.2 主要 CDN 横向对比(2024)
| CDN | HTTP/3 | 边缘计算 | 中国大陆 | 价格 |
|---|---|---|---|---|
| Cloudflare | ✅ 默认 | Workers (JS) | 需 ICP | 免费层慷慨 |
| Fastly | ✅ | Compute@Edge (Rust/Wasm) | 需 ICP | 中端偏贵 |
| Akamai | ✅ | EdgeWorkers | 需 ICP | 企业级贵 |
| AWS CloudFront | ✅ | Lambda@Edge | 需 ICP | 按用量 |
| 阿里云 DCDN | ✅ | EdgeRoutine (JS) | ✅ | 国内便宜 |
| 腾讯云 ECDN | ✅ | EdgeOne | ✅ | 国内便宜 |
国内业务选型:
- 国内用户:阿里云 DCDN / 腾讯云 ECDN(必须 ICP 备案)
- 海外用户:Cloudflare(免费层 + 简单配置 + 强 HTTP/3)
- 混合:国内 + 海外双 CDN,DNS 分流
6.3 CDN 缓存策略
Surrogate-Key 模式(Cloudflare / Fastly 支持):给每个资源打 tag,让 CDN 支持按 tag 批量失效:
# 响应头
Cache-Tag: post-123, user-456, category-tech
# API 调用批量失效
POST /cache-tags/invalidate
{ "tags": ["post-123"] }
生产案例:某新闻网站首页用 Cache-Tag: frontpage;发新文章时调一次 /cache-tags/invalidate { "tags": ["frontpage"] },比传统”按 URL 失效”快 1000 倍。
七、踩坑提醒(资深架构师请重点看)
- 不要盲目开启 HTTP/2 Push。Chrome 107 已删除 Server Push,Firefox 默认关。生产不要用。
- 不要混淆
Cache-Control: no-cache和no-store。前者缓存在本地但每次验证;后者完全不缓存。HTML 用 no-cache + ETag,用户数据用 no-store。 - 不要忽略 HTTPS 升级的中间状态。HTTP → HTTPS 切换期间,HTTP 页面里的 HTTPS 资源可能被 mixed content 阻止加载。用 HSTS preload + 301 全站跳转。
- 不要让 CDN 缓存 HTML。HTML 是动态生成的,CDN 缓存会导致用户看到旧版。HTML 用
no-cache,只在边缘做 SSL 卸载和压缩。 - 不要忽略 HTTP/3 的 UDP 防火墙问题。部分企业内网和旧防火墙只允许 TCP 443。降级策略:HTTP/3 失败时自动回退到 HTTP/2(QUIC 握手失败会被浏览器透明处理)。
总结
这一篇用 7 个关键事实把网络协议栈串起来:
- HTTP/1.1:队头阻塞 + 连接数限制 = 现代前端最大的优化目标。
- HTTP/2:二进制分帧 + 多路复用 + HPACK,单连接多流是核心。
- HTTP/3 + QUIC:UDP 之上的可靠传输,真正解决 TCP 队头阻塞。
- TLS 1.3:1-RTT 握手 + 0-RTT resume,HTTPS 不再拖慢首屏。
- 缓存策略:Cache-Control + ETag + Service Worker 4 层体系。
- CDN 选型:Cloudflare(海外)+ 阿里云/腾讯云(国内),HTTP/3 是默认选项。
- TLS 1.3 + 0-RTT:HTTPS 不再慢。
下一篇:前端安全——XSS / CSRF / CSP / SRI,从攻击面讲清楚怎么写不漏。
5 道重点面试问题方向
Q1(答案):HTTP/1.1 升级到 HTTP/2 解决了什么核心问题?HTTP/3 又解决了 HTTP/2 解决不了的什么问题?
A:HTTP/1.1 三大痛点:① 连接数限制(浏览器同域名 6 并发);② HTTP 层队头阻塞(请求按序响应);③ header 重复传输(每个请求都带完整 cookie / UA)。HTTP/2 通过 二进制分帧 + 多路复用 + HPACK 头部压缩全解决——单 TCP 连接跑多个 stream,header 用索引表压缩。HTTP/3(QUIC)解决 HTTP/2 解决不了的 TCP 层队头阻塞——QUIC 在 UDP 之上重建可靠性,每个 stream 独立,丢一帧不卡其他流。还有 1-RTT 握手(vs HTTP/2 2-3 RTT)和连接迁移(IP 变不断连)。面试要点:能说 HTTP/2 的 “HPACK 状态表同步” 为什么不能跨连接复用。
Q2(思考):TLS 1.3 相比 TLS 1.2 在握手延迟上做了什么优化?0-RTT 模式有什么安全风险?
Q3(思考):CDN 的核心价值是什么?国内 + 海外混合业务应该怎么选 CDN?Surrogate-Key 比传统 URL 缓存失效好在哪?
Q4(思考):浏览器缓存有哪 4 层?各自适合什么场景?stale-while-revalidate 策略的取舍是什么?
Q5(思考):你在生产环境里是怎么把首屏时间从 4.2s 优化到 1.8s 的?网络层具体做了什么改动?
💡 每道题后面都有 AI 助手按钮,可以一键拿到详细答案。
参考资料
- HTTP/3 Explained (Daniel Stenberg, Mozilla) — HTTP/3 与 QUIC 的标准解读
- High Performance Browser Networking (Ilya Grigorik) — 网络层全链路经典参考
- RFC 9114 — HTTP/3 — HTTP/3 协议原文
- RFC 9000 — QUIC — QUIC 协议原文
- RFC 8446 — TLS 1.3 — TLS 1.3 协议原文
- MDN: Cache-Control — Cache-Control 指令权威参考
- web.dev: HTTP Caching — Google 团队对缓存的实战指南
- Removing HTTP/2 Push (Chrome Developers) — Chrome 团队删除 Server Push 的原因