CDN HTTP看似简单,真正落地时却很容易踩坑。当你打开一个网页时,浏览器需要先下载HTML文档,解析后才发现还要去请求一堆CSS、JavaScript、图片。这种“先看文档、再请求资源”的模式,在慢速网络上会浪费大量等待时间。为了优化这个环节,工程师们想出了两种策略:HTTP/2 Server Push 和 HTTP 103 Early Hints。它们都试图让浏览器在拿到HTML之前就提前开始下载关键资源,但实现思路截然不同。今天我们就来拆解这两种机制,并重点聊聊它们在CDN边缘节点上的实际表现差异。
CDN HTTP:快速回顾:为什么需要预加载?
实际操作要点
想象你要组装一台家具,说明书(HTML)里写着需要用到螺丝刀和扳手(CSS、JS等资源)。传统流程是:你先读完说明书,然后起身去找工具。而预加载相当于:在你阅读说明书的同一时间,你的助手已经提前把螺丝刀和扳手递到了你手边。这就是Server Push和Early Hints想做的事——减少浏览器等待资源的时间。
但是,这两种助手的工作方式完全不同。一个“强行把工具塞给你”,另一个“悄悄把工具放在你旁边”。
HTTP/2 Server Push:服务器主动“推送”——CDN HTTP
我的处理经验
Server Push是HTTP/2协议引入的特性。当客户端请求一个HTML页面时,服务器可以“自作主张”地额外推送一些它认为浏览器接下来会需要的资源(比如CSS、JS),无需等待浏览器显式请求。听起来很理想对吧?但现实中有几个坑:
- 资源猜测不准:如果服务器把不需要的资源也推过来,浏览器可能已经缓存了这些文件,白白浪费带宽和连接。
- 连接阻塞:推送的资源会占用HTTP/2的多路复用流,影响其他正常请求的优先级。
- 浏览器缓存策略冲突:浏览器对推送资源有一套专门的缓存逻辑,有时反而导致资源重复加载。
在CDN边缘节点上实施Server Push时,边缘节点需要提前知道哪些资源是“热门推荐”。通常通过配置静态规则或使用服务端逻辑(比如根据URL模式)来触发。如果CDN代理的源站返回的响应头里包含Link头,有些CDN会自动启用Server Push。但实际部署中,Server Push的推送时机和资源选择很敏感,搞不好会拖慢整体加载。
延伸阅读:此处可内链到“CDN HTTP配置案例”相关文章。
103 Early Hints:服务器“暗示”而非“硬塞”
实际操作要点
103 Early Hints是HTTP/1.1的一个扩展状态码,于2019年正式标准化(RFC 8297)。它的思路更温和:服务器在发送最终响应之前,先发送一个103状态码的“提示信息”,告诉浏览器“你接下来可能需要这些资源,可以提前去请求了”。注意,这里只是说“可以”,并没有实际发送资源内容。浏览器收到103提示后,会主动发起对这些资源的请求,同时继续等待最终的200响应。
这种“暗示”的好处很明显:
- 尊重浏览器缓存:如果资源已经在缓存中,浏览器直接跳过请求,不会多浪费。
- 不抢占带宽:提示本身非常小(通常只有几个HTTP头),不会对传输造成负担。
- 灵活适配:服务器可以动态根据客户端特征(比如Cookie、User-Agent)决定提示哪些资源。
在CDN边缘节点上实现103 Early Hints通常更简单。CDN只需要在响应用户请求时,先返回一个103状态码,再返回完整的200响应。大部分CDN通过配置响应头或Edge Workers就能实现。例如,在Cloudflare或Fastly上,你可以编写一段逻辑:如果请求的是HTML页面,就在响应前插入103 Early Hints,提示加载首页的CSS和JS。
补充参考:此处可内链到“CDN HTTP故障排查实例”。
核心对比:在CDN边缘节点上的性能差异
为了直观理解,我们用一个简化场景:一个普通网页HTML文档大小约10KB,关键CSS+JS合计约50KB,服务器处理时间(TTFB)约200ms。
1. 首次加载(无缓存)
- 无任何优化:浏览器下载HTML(200ms + 传输时间),解析发现资源,再发起请求。总耗时 ≈ 200ms + 10KB下载 + 50KB下载(等待两个往返)。
- Server Push:服务器在发送HTML的同时,开始推送CSS和JS。但受限于TCP拥塞窗口,推送的资源可能和HTML共享带宽,实际节省的时间取决于初始窗口大小。在慢启动阶段,推送反而可能延缓HTML本身的交付,导致TTFB变长。测试数据显示,Server Push在多数真实场景下节省的时间并不明显,甚至可能拖慢。
- 103 Early Hints:服务器在200ms处理时间内,先发送103提示。浏览器收到后立即发起对CSS和JS的请求(并行),等200ms结束后,HTML开始传输的同时,CSS/JS可能已经下载了一部分。这样整体加载时间能减少约一个RTT(往返时间),效果稳定。
2. 二次加载(有缓存)
- Server Push:服务器依然会强行推送资源,即使浏览器本地已经缓存。这导致不必要的网络流量,尤其在移动端极不友好。虽然HTTP/2允许浏览器发送RST_STREAM取消推送,但反应延迟仍然浪费了带宽。
- 103 Early Hints:浏览器收到提示后,检查缓存发现已有资源,直接忽略,不会产生任何额外请求。完美规避浪费。
3. CDN层面的实施难度
- Server Push需要CDN节点具备动态决定推送哪些资源的能力,通常要配合源站的Link头或自定义脚本。而且推送列表需要与页面内容同步更新,稍有不慎就会导致旧资源推送给用户。维护成本较高。
- 103 Early Hints对CDN来说非常友好:只需要在边缘缓存一个“提示头列表”,在返回HTML时先发103就行。即使提示的资源发生了变化,影响也远小于推送。很多CDN已经原生支持,比如Google Cloud CDN、Cloudflare、Fastly。
实际测试数据参考
配置前的检查
根据公开的性能基准测试(例如Akamai、Cloudflare的相关博客),使用103 Early Hints的网页首屏加载时间平均减少5-15%,而Server Push在不同场景下的改善幅度不稳定,部分场景甚至出现负优化。谷歌Chrome团队也在2022年建议开发者放弃使用Server Push,转而使用103 Early Hints或Preload Links。原因是Server Push会干扰浏览器的预加载扫描器,而103 Early Hints更符合“发现-请求”的天然流程。
注意:上述数据来自行业实测,具体效果因网络条件、服务器配置、页面结构而异。建议在自己的CDN环境中通过A/B测试实际验证。
最佳实践:如何在CDN上配置103 Early Hints
实际操作要点
如果你当前在CDN边缘节点上考虑采用预加载优化,推荐优先尝试103 Early Hints。下面是一个通用配置思路(以使用Edge Workers或CDN引擎为例):
- 识别页面类型:只对HTML页面启用103 Early Hints,避免对API或静态资源误发。
- 确定提示资源:通常包括首屏渲染关键的CSS、JS以及字体文件。可以使用工具(如Lighthouse)的分析结果来筛选。
- 生成103响应:在CDN边缘节点逻辑中,当请求是HTML且尚未缓存时,先返回一个103状态码,并在Link头中指定预加载资源:
Link: ; rel=preload; as=style, ; rel=preload; as=script。 - 配合缓存策略:如果页面被CDN缓存,后续请求可以直接从缓存返回200,不需要再发103。但如果你希望即使是缓存命中也能提前预加载,可以在缓存响应前附加103。
- 监测效果:使用浏览器DevTools的Network面板观察时间线,对比启用前后“可交互时间”是否有改善。
想继续深入:此处可内链到“CDN HTTP优化清单”文章。
总结:谁更适合CDN边缘节点?
故障定位思路
在大多数情况下,103 Early Hints是更优的选择。它对缓存友好,实施简单,性能提升稳定,且没有Server Push的副作用。而Server Push虽然理论上更激进,但实际应用中容易踩坑,尤其是在CDN这种分布式环境中,资源列表的同步和更新是个难题。
当然,这并不意味着Server Push一无是处。在定制化程度极高的私有协议栈中,配合精细的推送逻辑,它仍然能发挥价值。但对于绝大多数站点,用103 Early Hints配合preload链接标签,已经能达到很好的首屏加速效果。
最后提醒一句:任何优化技术都要结合自身业务流量、用户设备、网络环境来评估。建议先在非关键路径上做对照测试,不要盲目全量开启。毕竟,让用户早点看到页面内容,比强行推送一堆用不到的资源更重要。真正做好CDN HTTP,靠的不是参数堆砌,而是持续验证。
延伸阅读
