Nginx 搭建 HLS 服务需与 CDN 协同设计:固定 m3u8 文件名、序号命名 ts 分片、显式设置缓存头;用 mp4 模块+Lua 动态切片;限制 CDN 回源 IP 与请求频率;通过日志变量精准定位缓存失效根因。

用 Nginx 搭建 HLS 流媒体服务本身不难,但要真正实现低延迟、高并发、就近响应的边缘加速效果,关键在于和 CDN 的协同设计——不是简单把 Nginx 接入 CDN,而是让 Nginx 成为 CDN 边缘节点的“智能前置”,承担动态切片生成、访问控制、缓存策略细化等任务。
让 Nginx 输出符合 CDN 友好规范的 HLS 清单与分片
HLS 加速成败,第一步就卡在 m3u8 和 ts 文件能否被 CDN 高效缓存并快速回源。默认 Nginx 不做特殊配置时,m3u8 常带动态参数(如时间戳、token),导致 CDN 认为每个请求都是新资源,无法复用缓存。
建议做法:
- 固定 m3u8 文件名(如 index.m3u8),不拼接 query 参数;若需鉴权,改用 HTTP Header(如 X-Auth-Token)或 Cookie 传递凭证,CDN 可按规则透传或校验
- ts 分片命名使用递增序号(seg-1.ts, seg-2.ts),避免时间戳或哈希值;确保 EXT-X-MEDIA-SEQUENCE 严格递增且不跳变,方便 CDN 合理设置 TTL
- 在 Nginx 中显式设置缓存头:add_header Cache-Control "public, max-age=3";(ts 文件可设为 3 秒,m3u8 设为 1 秒),让 CDN 明确知道内容时效性
用 Nginx 实现轻量级动态切片与热重载(替代完整转码)
边缘节点不适合跑 FFmpeg 实时转码,但可以利用 Nginx 的 http_mp4_module 或配合 nginx-rtmp-module(启用 HLS 模块)做“伪实时”切片:将已转好的 MP4 源文件,按需动态生成最新几秒的 m3u8 + ts 列表,既降低 CPU 开销,又保证“准实时”体验。
典型配置片段:
- MP4 源放在本地 SSD 或高速 NAS,通过 location /hls/src/ 暴露只读路径
- 用 mp4 指令支持 range 请求,并启用 mp4_buffer_size 提升首帧加载速度
- 搭配 Lua 脚本(OpenResty)动态计算当前应返回的最后 N 个 ts 片段,写入临时 m3u8,再由 CDN 缓存该清单(注意设置短 TTL 并开启 stale-while-revalidate)
在 Nginx 层做 CDN 回源流量整形与黑白名单控制
CDN 回源并非完全可信——恶意爬虫可能绕过 CDN 直连源站,或某地 CDN 节点异常触发大量回源请求,压垮 Nginx。必须在 Nginx 上做第一道防线。
- 只允许已知 CDN IP 段回源(如 Cloudflare、阿里云全站加速、腾讯云 CDN 的官方回源 IP 列表),其余全部 deny all
- 对合法回源 IP 设置独立限流:用 limit_req_zone $binary_remote_addr zone=cdn:10m rate=100r/s,防止单个 CDN 节点突发刷量
- 对 m3u8 请求启用更严策略:limit_req zone=hls_list burst=5 nodelay,因清单更新频繁但总量可控,过载易引发连锁雪崩
利用 Nginx 变量与日志精准定位 CDN 缓存失效根因
用户卡顿?首屏慢?不能只查 CDN 控制台。Nginx 日志里藏着真实回源行为:是否命中缓存、是否被 CDN 强制刷新、客户端真实地域等。
- 在 log_format 中加入:$upstream_http_x_cache $upstream_http_x_cache_age $http_x_forwarded_for $http_user_agent
- X-Cache: HIT/MISS/EXPIRED 来自 CDN 回源响应头,直接反映边缘节点状态
- 结合 $request_time 与 $upstream_response_time 差值,判断是 CDN 延迟还是源站响应慢
- 用 Logstash 或 Grafana+Loki 对 “MISS+高频 m3u8 请求” 组合告警,快速发现缓存规则配置错误或热 key 未预热

















