腾讯云 COS + EdgeOne 静态资源分发实践
自建社区类项目积累了一批用户上传的静态资源(图片、皮肤文件、安装包),这套”COS 存储 + EdgeOne 分发”的组合用了很久,把架构决策和踩坑记录下来。
核心架构:上传下载分域名
1 | 客户端上传 ──→ cos.example.com(COS 默认源站域名)──→ 存储桶 |
上传和下载走不同域名,这不是闲得无聊,是三个现实原因:
- 流量计费分离:CDN 的流量是单独计费的,上传如果挤占 CDN 回源通道,既慢又可能产生不必要的费用;
- 上传接口可以单独做鉴权:上传域名只开放 PUT/POST 和必要的预检,不挂公开缓存策略;
- 下载域名可以挂满缓存和防盗链:公开读、长缓存、Referer 白名单,两者互不干扰。
存储桶基础配置
创建 bucket 后第一件事不是传文件,是把这几个开关设好:
- 权限:公有读私有写。下载域名要能匿名读,写入只允许带签名的请求或服务端中转;
- 版本控制:开。用户上传的文件被覆盖时能找回,成本极低;
- 生命周期:90 天前的低访问量文件转低频存储,配合版本数限制(保留最近 3 个版本),防止版本堆积把存储费用拉爆。
文件类型校验:扩展名会骗人
做皮肤文件上传时踩过的坑:文件后缀是 .scskin,但内部格式可能是 PNG,也可能是 WebP。如果只按扩展名放行,用户把任意文件改名成 .scskin 就能上传。
正确的校验姿势是读文件头(magic number):
1 | import struct |
策略:
- 白名单制:只放行
image/png和image/webp两种,JPEG 一律拒绝(皮肤贴图用有损格式会出现色带,社区明确不欢迎); - 服务端嗅探,不信客户端:
Content-Type是客户端自带的,想造假成本为零; - 大小上限:图片类 5MB 封顶,超限直接拒,别等上传完再删。
EdgeOne CDN 配置要点
接入 EdgeOne 后,下载域名 cdn.example.com 上配这几项:
| 配置 | 值 | 理由 |
|---|---|---|
| 缓存规则 | 图片/静态文件 30 天 | 内容不变则长缓存,文件名带 hash 时更省心 |
| 回源 HOST | cos.example.com | 指回 COS 源站 |
| Referer 防盗链 | 仅允许自己的站点域名 | 防别的站贴图蹭流量 |
| 压缩 | Brotli + Gzip | 文本类资源再省一截 |
防盗链的代价:空 Referer 要放行(用户地址栏直开、App 内请求都可能不带 Referer),只拦”Referer 存在且不在白名单”的请求,否则容易误伤。
免费套餐的成本控制
EdgeOne 免费额度对小项目完全够用,但有两个隐性消耗点要注意:
- 回源流量:CDN 没命中时回源拿的流量另算,缓存规则配得合理就是省钱;
- 刷新/预热调用次数:文件更新后主动刷新 URL,免费额度内省着用,文件名带内容 hash 的话根本不需要主动刷新。
签名 URL:给私有资源开临时门
有些资源不能公开读(比如用户私有的皮肤),用预签名 URL:
1 | import hashlib, hmac, time, base64 |
过期时间给 5 分钟足够客户端拉起文件,又不会让链接满世界飞。CDN 层配”忽略指定参数缓存”或开启签名校验,按安全级别二选一。
小结
这套组合的关键决策就三个:上传下载分域名、文件类型服务端嗅探、长缓存 + 防盗链。免费套餐下把回源流量管住,成本可以压到接近零,性能却比传统”服务器直出文件”高一个量级。