1.
目标与准备工作
说明目标:降低延迟、减少回源、保证播放稳定性。
准备项:已部署源站(Nginx/OBS/SRS)、可配置 CDN(CloudFront/Cloudflare/阿里/腾讯)、播放器(HLS.js、Shaka、原生 iOS/Android)、日志与监控工具(Prometheus/CloudWatch)。
输出指标:播放延迟(s),切片丢失率,CDN 命中率,回源流量。
2.
理解 HLS 流与缓存要点
HLS 组成:M3U8 manifest(主 playlist/variant) + TS/FLV/MP4 分片(segment)。
缓存原则:不可缓存 live master manifest 太久;分片可缓存但需考虑实时性与片段更新。
关键头:Cache-Control、Expires、ETag、Last-Modified、Vary、Surrogate-Control(部分 CDN 支持)。
3.
CDN 端缓存策略设计(总体流程)
步骤概览:设置缓存键 → 设置 TTL 与边缘刷新规则 → 支持分片预取/回源限速 → 配置回源缓存与条件请求。
建议:对 playlist 使用短 TTL(1-3s),对 segment 使用较长 TTL(10-30s,视直播延迟要求)。
4.
CDN 具体配置步骤(以常见场景为例)
CloudFront/阿里/腾讯 步骤:创建行为规则(Behavior),指定缓存路径(如 *.m3u8, /live/*/index.m3u8)→ 设置缓存基于请求头或查询字符串(保留播放必要参数)→ 设置 TTL(最小/默认/最大)。
注意保留:Range 支持、Origin Shield(可选)和回源限流策略。
5.
Origin(源站)配置与响应头控制
Nginx 示例:对 m3u8 设置 add_header Cache-Control "max-age=2, must-revalidate"; 对 segment 设置 add_header Cache-Control "public, max-age=30"; 启用 ETag 与 If-Modified-Since 支持。
实际步骤:编辑 site 配置 → 在 location 写明路径及头 → reload nginx → 验证 curl -I URL。
6.
播放器端缓存与拉流逻辑调整
播放器策略:短轮询 playlist(根据 playlist 的 EXT-X-TARGETDURATION 调整刷新间隔),保持小缓冲区避免高延迟,缓存已下载分片并重用。
实现细节(HLS.js):设置 loader 自定义拦截器以读取缓存、在请求头中加上 If-None-Match/If-Modified-Since 实现 304 减量回源;在 segmentResponse 处理里判断 304 返回复用本地已缓存数据。
7.
结合 Service Worker / IndexedDB 做客户端缓存(可选)
先决条件:必须能控制播放器环境(Web)。
实操步骤:注册 Service Worker → 在 fetch 事件中拦截 m3u8 和 segment 请求 → 对 segment 使用 Cache API 或 IndexedDB 存储并返回缓存副本;对 m3u8 仅缓存非常短时间或直接走网络。
注意点:避免无限制增长,定期清理旧 segment,采用 LRU 策略,保证内存与磁盘配额。
8.
缓存协同细则:如何保证 CDN 与播放器一致性
约定缓存键:统一去除无意义 query(如统计参数),对关键参数(分辨率、码率)保留。
缓存一致策略:使用 Surrogate-Control(CDN)与 Cache-Control(浏览器/播放器)组合;在分片更新时通过 CDN API 触发按路径精确清理(purge)而非全量清理。
示例:发布关键切片时调用 CDN 的 purge 对应 /live/stream1/*.ts。
9.
测试与监控步骤
验证步骤:1) 用 curl 获取 M3U8 验证 Cache-Control 与 ETag;2) 在不同节点(本地/境外)验证 CDN 命中率;3) 人为更新分片观察玩家是否能及时拿到新内容。
监控指标:CDN 命中率、回源带宽、播放 start-up time、buffering events、播放成功率。使用 CDN 控制台和播放器日志联合分析。
10.
常见问题与解决办法
问题一:切片更新但播放器仍播放旧片段。解决:检查 CDN TTL 与是否需要 purge;播放器是否缓存了旧段并未检测 304。强制在 playlist 上加上序列号或版本号作为 query 以避免缓存不一致。
问题二:回源激增。解决:提高 segment TTL、启用预热/预取、启用 Origin Shield 并优化回源并发。
11.
示例配置片段(Nginx + CloudFront 思路)
Nginx 配置示例:location ~ \.m3u8$ { add_header Cache-Control "max-age=2, must-revalidate"; } location ~ \.(ts|mp4)$ { add_header Cache-Control "public, max-age=30"; }。
CloudFront:Behavior pathPattern = *.m3u8 TTL 2s;pathPattern = *.ts TTL 30s;Whitelist Headers 包含 If-Modified-Since, If-None-Match;Enable Cache Based on Query String (保留必要参数)。
12.
问:如何在不增加延迟的前提下提高 CDN 命中率?
答:对 playlist 设置极短 TTL(1-3s)保证实时性,对 segment 设置相对更长 TTL(10-30s)以提高命中率;通过播放器端合理缓冲(3-6 segments)减少重复请求;启用 CDN 预取/HTTP2 推送(若 CDN 支持)提前下发关键分片,并对不必要的请求(统计、心跳)走不同域名以不污染缓存键。
13.
问:播放器如何优雅处理 304 返回以减少回源?
答:播放器在遇到 304 时应复用本地已缓存的 segment 数据而不是再次下载;实现方法是在自定义 loader 中保存最近的 segment 内容与 ETag,当收到 304 时直接从内存/IndexedDB 返回缓存数据并更新播放队列;同时记录 ETag/Last-Modified 以便下次使用条件请求。
14.
问:发生紧急切片替换时如何快速让全网生效?
答:最佳做法是:1) 在源端上架新分片并增加版本号或在路径上加入时间戳;2) 调用 CDN 的按路径 Purge API 精确清理受影响的分片与其对应的 playlist;3) 播放器端在检测 playlist 版本变更时优先拉取新 playlist 并清理本地过期分片。配合监控确认 CDN 命中率与回源下降。