logo NodeSeekbeta

关于cdnfly缓存配置分片回源的bug避坑指南

当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/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 回源:

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 边缘节点处理逻辑缺陷:

  1. 源站 Next.js 应用返回 Transfer-Encoding: chunked(分块传输),且无 Content-Length。
  2. CDN 开启“分片回源”后,边缘节点期望按照 1MB 为单位向源站请求数据块。
  3. 当面对动态边界的分块流时,CDN 内部的流重组与缓存状态机出现错乱。
  4. 在向用户端(浏览器)封装 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

  • 渗流:cdnflu开启分片回源后,当源站返回 Transfer-Encoding: chunked 且无 Content-Length 的响应时,CDN 边缘节点向客户端发送 HTTP/2 数据帧时会出现协议错误(ERR_HTTP2_PROTOCOL_ERROR)。建议cdnfly技术修复分片回源模块对 chunked 流的处理逻辑,或在内部强制缓冲 chunked 响应后再进行分片操作。

  • 学习了!

你好啊,陌生人!

我的朋友,看起来你是新来的,如果想参与到讨论中,点击下面的按钮!

📈用户数目📈

目前论坛共有72267位seeker

🎉欢迎新用户🎉