最近在部署一个 HTTPS 站点(love214.qingyang.ai)时,遇到了一个非常隐蔽但典型的线上问题:
页面可以正常访问,但音频资源 love-song.mp3 无法播放,浏览器控制台报错:
Failed to load resource: the server responded with a status of 416 ()
乍一看像是 Nginx Range 支持问题、音频文件损坏,甚至是前端播放器问题。但最终定位发现,真正的根因来自 Cloudflare 的错误缓存副本。下面完整复盘这次排障过程与最终的工程化解决方案。
一、问题现象
1)浏览器播放 MP3 失败
Chrome 控制台报错 416(Range Not Satisfiable)
2)直接访问音频 URL
https://love214.qingyang.ai/love-song.mp3
页面能返回,但播放器请求 Range 时失败。
3)同样请求走 HTTP 或直连源站是正常的
说明问题只发生在走 Cloudflare CDN 的 HTTPS 路径。
二、快速定位思路
音频、视频播放的 HTTP 特性:
浏览器会自动发送 Range 请求,例如:
Range: bytes=0-1023
因此关键判断点是:
👉 CDN / 代理是否正确支持 Range + 正确缓存了完整文件。
三、对比源站与 Cloudflare 的响应
对源站测试:
curl -I -H "Range: bytes=0-1023" http://127.0.0.1/love-song.mp3
返回:
- HTTP 206 Partial Content
- Content-Length 正常
- Accept-Ranges: bytes
说明:
✔ 源站文件没问题
✔ Nginx 支持 Range
✔ MP3 文件本身正常
对 Cloudflare 测试:
curl -I -H "Range: bytes=0-1023" https://love214.qingyang.ai/love-song.mp3
返回:
- HTTP/2 416
- Content-Length: 0
- Content-Range: bytes */0
这一步非常关键:
Cloudflare 缓存了一个 0 字节的 MP3 副本,
导致浏览器 Range 请求命中缓存后直接 416。
四、根因总结
问题本质不是:
❌ 前端播放器问题
❌ MP3 文件损坏
❌ Nginx 未支持 Range
而是:
✅ Cloudflare 曾经抓取音频时发生异常
✅ CDN 缓存了一个 Content-Length = 0 的错误副本
✅ 后续所有 Range 请求都命中这个坏缓存
✅ 直接导致 416,音频无法播放
五、工程级修复方案
目标:
既修复当前问题,又防止将来再次出现同类事故。
方案 1:Cloudflare 对音频资源禁用缓存(长期方案)
在 Cloudflare → Rules → Cache Rules 中新增规则:
If incoming requests match(自定义条件)
- URI Path ends with
.mp3 - OR
.ogg - OR
.wav
Then
- Cache eligibility: Bypass cache
含义:
音频资源永远不走 CDN 缓存,直接回源,避免缓存层污染。
方案 2:立刻清除坏缓存(一次性)
Cloudflare → Caching → Purge Cache → Custom purge
填入:
https://love214.qingyang.ai/love-song.mp3
清掉已经存在的 0 字节副本。
方案 3:Nginx 源站侧增加缓存防护头(双保险)
在 Nginx 对音频资源加明确响应头:
location ~* \.(mp3|ogg|wav)$ {
add_header Cache-Control "no-store" always;
add_header Accept-Ranges "bytes" always;
try_files $uri =404;
}
含义:
- no-store:明确告诉 CDN 和浏览器不要缓存
- Accept-Ranges:明确支持 Range
- 避免中间层“猜测式缓存”音频流
六、验证修复是否成功
curl -I -H "Range: bytes=0-100" https://love214.qingyang.ai/love-song.mp3
正确结果应为:
- HTTP 206 Partial Content
- Content-Length > 0
- 音频可在浏览器中正常播放
七、经验总结
这次问题的典型特征是:
- 只在 HTTPS + CDN 访问路径异常
- 源站完全正常
- 表现为 416 / Range 错误
以后再遇到类似问题,可以直接按这个路径排查:
1)源站 Range 是否正常
2)CDN 是否命中缓存
3)Content-Length 是否异常为 0
4)CDN 是否缓存了流媒体资源
5)是否需要对大文件 / 流媒体禁用缓存
八、通用工程建议
1)音视频文件不要默认交给 CDN 自动缓存
2)流式资源建议显式设置 Cache-Control
3)Range 相关问题优先对比“源站 vs CDN”
4)线上 416 大概率不是应用逻辑问题,而是缓存层污染
5)对 CDN 的缓存策略要做“白名单”,不要全量默认缓存