4.3 CDN 分发与防盗链

文件在 COS 里放好了,学生看回放时直接从对象存储拉——能看,但慢。对象存储的访问节点就那么几个,平时跑跑后台没问题,一旦几十个学生同时从各地拉视频,延迟和带宽都顶不住。更危险的是:COS 的流量单价不便宜,直连意味着所有流量都按对象存储的价格走。这一节讲我怎么把回放挂到 CDN 上,以及差点被刷光流量的一次事故。

CDN 的原理和接入步骤,官方的内容分发网络文档有完整说明,这里只讲课堂场景的实践。一句话理解 CDN:它把你的视频提前复制到全国各地的节点上,学生从最近的节点取数据,既快又便宜,回源这一层流量由 CDN 扛。对回放这种读多写少的场景,CDN 简直是为它设计的。

接入四步走

步骤 操作 我踩过的坑
第一步 加域名 在 CDN 控制台添加一个回放子域名 域名要提前完成备案
第二步 配源站 源站指向 COS 存储桶域名 源站类型记得选对象存储
第三步 改 CNAME 到域名解析处加 CNAME 指向 CDN 分配的域名 生效要等几分钟到几小时
第四步 验证 多地域访问确认走了 CDN 节点 别只看本地,不同网络都测

第三步是新手最容易卡住的:CNAME 加了但没生效,就以为配错了反复改解析。其实用解析工具看一眼结果就知道有没有生效,生效后响应头里会带上节点标识。整个接入过程不复杂,但第一次跑建议挑晚上没课的时候,留出调试窗口。域名规划也有讲究:回放域名和我们主站域名分开,这样回放流量再大也不影响主站解析,出问题时隔离也更干净。我们用的是 play 点我们的域名,一看就知道是回放专用,日常排查日志也清楚。

接入完成后别急着让线上流量切过来。我们先在测试环境跑了一周:拿几节旧课回放挂在测试域名上,在公司网络、家庭宽带、手机 4G 各测一遍,确认缓存命中和首屏速度都正常,才把正式域名切过去。这种灰度切换的习惯,是从《1Panel 常见问题与排错实战》里学的:线上变更永远先小范围验证,直播平台这种学生随时在用的系统尤其不能莽撞。

缓存命中率的日常观察

上个小结说了缓存规则,这小结说说怎么盯它。我们每天早上会扫一眼前一天的命中率报表,顺手看回源流量占比。正常的曲线是平稳的,有波动先看是不是有新课首播——新课第一天的前几个小时命中率为零是正常的,预热做了之后这种情况也少了。

观察指标 正常水位 异常时查什么
缓存命中率 95% 以上 新目录是否漏配规则
回源流量 总量的零头 命中率是否下滑
节点回源失败 几乎为零 源站 COS 是否正常
请求状态码 全是 200 或 206 是否被刷或鉴权失效

这张表是我们运维值班的第一页,出现异常按表逐项查,比凭感觉排查快得多。监控告警的搭建不在本节展开,下一篇讲上线运营时会细说。

缓存策略

CDN 的核心价值是缓存,但配置不当会出两类问题:学生看到旧视频,或者缓存命中率低、回源把源站带宽打满。我的策略是按资源类型分层设置。

资源类型 缓存时间 理由
回放视频(MP4) 30 天 内容不变,越久越省
HLS 切片文件 30 天 切片不可变,同上
回放封面图 7 天 可能替换,留个缓冲
课程列表接口 5 分钟 排课经常变,要及时
静态页面 1 天 更新频率低,容忍滞后

视频文件天然适合长缓存:录播内容发布后永不修改,要改就传新版本走新路径。但注意,路径带版本号是前提——如果回放内容直接覆盖同一路径,长缓存就会变成学生永远播旧视频的事故。4.2 节定的日期目录层在这里救了命:每次重录自动走新路径,缓存和版本控制天然不冲突。另外缓存规则是按前缀匹配的,不同课型的目录前缀要分开写规则,别指望一条规则覆盖所有文件。有一种例外要特别留意:运营临时修改了某节课的老师信息页或者封面,这类小文件如果命中长缓存,改了不生效又是一轮客诉。所有需要人工修改的内容,一律走独立路径加版本号,让缓存规则和内容版本相互配合而不是互相打架。

命中率是这套策略的核心指标,值得每天扫一眼。我们的命中率稳定在 95% 以上,哪天掉到 90% 以下,大概率是某个新目录前缀没配缓存规则,回源直接打到 COS。有一次就是这样:新开的一期课回放路径变了,缓存规则没跟上,当天晚上 COS 回源流量告警,补上规则后立刻恢复。从那次起我们养成了个习惯:新一期课开课前,缓存规则和播放路径一起进检查清单,运营开课时跑一遍,不再等问题发生。

流量成本怎么看

接 CDN 之后最直观的变化是账单结构变了:原来全是 COS 流量费,现在变成了 CDN 流量费加少量回源流量费,总价便宜不少,但用量一旦上来仍然是大头。月度账单里我们会把流量按课型拆开看:正课回放的流量稳定可预测,跟排课量线性相关;公开课回放的流量弹性大,某一节公开课如果被分享了,流量可能是平时的好几倍。

成本科目 观察重点 控制手段
CDN 流量 按课型拆分看波动 防盗链加缓存命中率
回源流量 应趋近于零 命中率告警兜底
存储容量 月度环比增幅 生命周期规则

这张表我们每月复盘一次,哪一项异常就回头查对应的配置。成本管理这件事在《腾讯云实战手记:从云服务器到短信推送的全栈上线》里有更系统的做法可以参考,核心思想一样:把账单按业务维度拆开,才看得出问题,只看一个总数是发现不了异常的。

防盗链

回放域名是公开的,谁都能来拉流量。防盗链不是可选项,而是上线前必须配好的最后一道闸。

手段 原理 适合场景
referer 防盗链 只允许指定来源页面访问 拦截最低成本的嵌入盗链
URL 鉴权 播放地址带签名和有效期 与课程权限打通的核心手段
IP 限频 单 IP 限制请求频率 防爬虫式的批量刷流

我们三层都开了,但真正兜底的是 URL 鉴权:播放地址由服务端签名,过期时间设为 2 小时,学生离开页面后链接即失效。这一层的细节在下一节 4.4 鉴权播放里展开。另外防盗链规则更新后记得刷新旧缓存,否则规则生效了但节点上还按旧规则放行,会给你一种没配成功的错觉——这种玄学问题最折磨人,其实是缓存没刷新。防盗链三层不是彼此孤立的,配合起来才能兼顾安全和体验:referer 拦掉最低成本的外站嵌入,URL 鉴权保护核心资产,IP 限频挡住脚本批量刷。任何一层单独用都有明显短板,三层一起才是小团队能负担得起的完整防线。

一次被刷流量的事故

上线第三个月的一个周日早上,我收到流量告警:回放域名一小时跑了将近 200GB,是平时峰值的十倍。登上后台一查,是一个没登记过的来源站点在疯狂拉我们的公开课视频——他们在自己网站里嵌了我们的播放地址,白嫖流量给他们的用户看。要不是告警及时,一天的账单可能比一个月还高。

紧急处理分三步:先把 referer 防盗链开启,拒绝所有不在白名单的来源,流量应声而降;再把被嵌最多的几个公开课视频路径换掉,旧路径直接返回不存在,新路径重新生成签名;最后排查为什么 URL 鉴权没拦住——发现是早期给合作方生成的几个公开课链接漏配了过期时间,成了永久直链,当晚全部改成短期鉴权地址。

事故复盘的结论有三条。第一,防盗链配置一定要自动化巡检,人手配的总有漏的。事后我写了个脚本每周扫描所有生效的播放域名,列出没有鉴权或缓存异常的路径,这个简单的习惯比任何复杂架构都管用。脚本跑在一台小服务器上,服务器本身的维护可以看《轻量应用服务器建站实战:从选购到网站上线》。第二,告警阈值要按业务峰值设富余量,我们的事故告警设得很及时,就是得益于那天早上随手调过一次阈值,否则流量账单还会更高。第三,事故期间查访问日志排查来源的过程,和《AI 语音转写实战:搭建会议纪要工具》里分析长录音的思路一样:先过滤再归因,别被海量明细淹没。整个复盘我也整理进了《腾讯云实战手记:从云服务器到短信推送的全栈上线》的运维章节。

多说一句事故之后的善后:被白嫖的那几天流量我们承担了,但也因此把公开课的鉴权策略彻底重做。现在所有公开课回放一律走短期签名,合作方要嵌播放必须走我们的白名单域名报备,不再有任何永久直链存在。同时保险起见,我们给 CDN 设了带宽上限告警,单小时流量超过阈值立刻通知,宁可误报也不漏报。小团队没有专职安全岗,这套机制跑下来半透明、低成本,足够管用。

事故还带来一个意外收获:我们发现被刷的那几个公开课回放,完播数据出奇地好,说明内容本身是有吸引力的。后来我们把这几节课剪辑成短视频重新投放,转化率不错。坏事里挑点好事,也是复盘的价值之一。

延伸阅读