当cdnfly与next应用一起搭配使用的时候会遇到http2.1协议不兼容的问题导致网站异常卡顿,在和deepseek一起花了一天的时间解决了这个问题以后我决定把内容发布出来。以下内容由ai生成
AI:
记一次诡异的 ERR_HTTP2_PROTOCOL_ERROR 200 排查:CDN“分片回源”与源站 Chunked 传输的兼容性缺陷
1. 环境与架构
服务器:国内 NAT 机 + 1Panel 面板
后端:Next.js 应用,部署在 Docker 容器中(
docker-compose编排),通过8091端口映射网关:OpenResty 反向代理,处理 HTTPS 并转发至容器
加速:某国产 CDN(国际节点),回源固定 HTTPS,用户侧 HTTP/2,回源 HTTP/1.1
2. 诡异现象
同一台服务器上部署了 6 个配置完全相同的网站。
其中 2 个网站 访问卡顿,浏览器控制台报错:
net::ERR_HTTP2_PROTOCOL_ERROR 200 (OK)直连源站(修改本地 hosts 绕过 CDN)一切正常,丝般顺滑。
其他 4 个网站 通过 CDN 访问也完全正常。
3. 排查过程(关键步骤)
第一步:对比响应头
在服务器本地分别 curl 异常网站和正常网站,返回头完全一致(均为 Next.js 典型响应):
HTTP
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Cache-Control: s-maxage=60, stale-while-revalidate=31535940
Vary: rsc, next-router-state-tree, next-router-prefetch, next-router-segment-prefetch, Accept-Encoding
Etag: "xxx"
X-Powered-By: Next.js
初步排除非法响应头或大 Cookie 问题。
第二步:模拟 CDN 回源请求
使用 curl 强制 HTTP/1.1 并禁用缓冲,模拟 CDN 回源:
BASH
curl -k -v --http1.1 --no-buffer -H "Host: blog.xxx.top" http://127.0.0.1:8091/ > /dev/null
结果:连接稳定,数据完整接收,无任何中断。说明 OpenResty → 容器链路完好。
第三步:关注传输编码差异
HEAD请求返回Content-Length: 67853。GET请求返回Transfer-Encoding: chunked。
此时焦点转移至 CDN 对分块传输响应的处理逻辑。
第四步:定位 CDN 配置项
检查 CDN 控制台,发现可疑功能 “分片回源”。根据官方文档说明:
开启后,CDN 会将大文件分片从源站回源,每次仅获取并缓存 1M 内容。
第五步:最终验证
关闭“分片回源” → 问题 立即消失。
开启“分片回源” → 问题 稳定复现。
4. 根因分析
这是一起典型的 CDN 边缘节点处理逻辑缺陷:
源站 Next.js 应用返回
Transfer-Encoding: chunked(分块传输),且无Content-Length。CDN 开启“分片回源”后,边缘节点期望按照 1MB 为单位向源站请求数据块。
当面对动态边界的分块流时,CDN 内部的流重组与缓存状态机出现错乱。
在向用户端(浏览器)封装 HTTP/2
DATA帧时,CDN 生成了长度声明与实际数据不符的违规帧,触发浏览器协议层报错。
由于各网站首页的具体 chunk 边界分布不同,仅部分网站触发了该底层 BUG。
5. 解决方案(三选一)
方案 | 操作 | 利弊 |
|---|---|---|
A. 关闭分片回源 | CDN 控制台直接关闭该功能。 | 推荐。简单有效,彻底规避。 |
B. 源站禁用 Chunked | 在 OpenResty 中强制开启 proxy_buffering on;,让网关吐出带 Content-Length 的完整响应。 | 需消耗少量内存缓冲,但能保留分片回源功能。 |
C. 关闭 CDN 缓存 | 将动态页面设为不缓存,仅缓存静态资源。 | 增加源站压力,但最稳定。 |
6. 总结与反思
ERR_HTTP2_PROTOCOL_ERROR背后往往是链路中间设备对协议实现的兼容性瑕疵,而非源站代码问题。分块传输(Chunked) 在 HTTP/1.1 中合法且常用,但遇到自定义处理逻辑(如分片缓存、WAF 深度检测)时风险极高。
测试时务必使用
curl --no-buffer模拟真实数据流,简单的-I头请求无法暴露此类问题。如果你的 CDN 支持 HTTP/2 回源,开启后有时也能规避此类协议转换 BUG。
希望此记录能帮助遇到同样报错的同学少走弯路。如果你使用的也是类似架构的 CDN,建议直接检查“分片回源”开关。
AI文结束了,最后说个关于我在用的国人某失控cdn的专属很傻的隐私安全问题(当然我已经反馈他修复了),他的网站上有个功能是输入用户id判断是否有这个用户,有就返回加群链接,问题是这个功能调用的接口返回的数据包含用户隐私信息,ID、手机号、邮箱全部都会被接口返回,没有做匿名处理,唯一的防护就是一个人机验证码,据我所知他的这个功能已经上线二年多了,也就意味着过去的两年中他的cdn站点几千用户等同于在互联网裸奔。网络安全刻不容缓啊 :xhj004:


