CDN
在 ImgYoung 前面加 CDN:缓存头、WebP 协商与 Vary、按需处理的缓存键、Cloudflare 缓存清除,以及 302 模式和防盗链在 CDN 后的表现。
推荐模式:代理 + CDN
CDN 回源到 ImgYoung(经反向代理),访问模式保持 proxy:
- 图片字节由 ImgYoung 从渠道读出,渠道故障在回源时即时切换,CDN 只看到一个稳定的源站;
- 按需处理(
?w=、?format=)与 WebP 协商照常工作,结果由 CDN 缓存; - 对外域名是 CDN 的域名,所以要在后台设置
base_url(「设置 → 运行配置 → 访问与链接 → 对外站点地址」),并把 CDN 的回源网段加进IMGYOUNG_TRUSTED_PROXIES,登录限速才能按真实访客计,见反向代理与 HTTPS。
只缓存图片入口 /i/* 与 /o/*;/api/*、/s3/* 应设为不缓存。后台页面的 index.html 带 no-cache,/assets/ 下的文件名带内容哈希并带一年强缓存,随 CDN 默认规则即可。
缓存头
图片入口的响应头:
| 响应 | Cache-Control | ETag | Vary |
|---|---|---|---|
/i/<短ID> 的原图 | public, max-age=31536000, immutable | "<sha256>" | 未指定 format(或 format=auto)访问 JPEG / PNG / WebP 时为 Accept |
/i/<短ID> 的衍生图(缩放或转格式) | 同上 | "<sha256>-<宽度>-<格式>",不缩放时宽度为 0 | 目标格式由协商得出时为 Accept |
/o/ 别名的原图与衍生图 | public, no-cache | 同上 | 同上 |
| 按需处理失败、回退的原图 | no-store | 无 | 无 |
If-None-Match 命中 | 304,带对应的 Cache-Control、ETag 与 Vary | ||
302(redirect 模式) | no-store | 无 | 无 |
| 参数非法(400)、防盗链拒绝(403)、不存在或已到期(404)、查询元数据失败(500,可重试) | 无 | 无 | 无 |
原图响应另带 Last-Modified(上传时刻)。/i/<短ID> 绑定的内容永不改变,所以按一年强缓存。
/o/<用户 ID>/<对象键> 是 S3 客户端自取的别名,同一对象键重新上传时别名会改指新图,所以它的响应允许缓存,但每次使用前都要带 ETag 回源确认:内容没变得到 304,改指后得到新图,删除后得到 404。经 CDN 对外时,/i/ 链接的缓存效果更好。
WebP 协商与 Vary
不带 format 参数(或 format=auto)访问 JPEG / PNG 图片时,如果请求头 Accept 含 image/webp、且「目标格式」里有 webp,返回的是 WebP 衍生图,否则返回原格式。也就是说,同一个 URL 会按 Accept 返回不同格式,两种响应(包括 304)都带 Vary: Accept。
CDN 必须按 Accept 区分缓存(遵守 Vary: Accept,或把 Accept 纳入缓存键),否则先被缓存的 WebP 会发给不支持 WebP 的客户端。Cloudflare 可以在 Cache Rules 中配置对 Vary 的处理,其他 CDN 以各自文档为准。CDN 做不到时,在后台「按需处理 → 目标格式」里去掉 webp:不再发生协商,代价是 ?format=webp 也随之不可用。
按需处理参数与缓存键
w必须是「宽度档」里的值,format必须是「目标格式」里的值或auto,否则返回 400。白名单限定了一张图最多有多少种衍生图,任意参数打不出无限多的缓存条目。- 其他查询参数被 ImgYoung 忽略,却会进入 CDN 默认的缓存键:给 URL 随便加个参数就能绕过缓存直接回源。建议把缓存键的查询串限定为
w和format。 - 参数顺序固定写成
?w=…&format=…。缓存清除只按这个顺序清理(见下节),顺序不同的 URL 在 CDN 看来是另一条缓存。
Cloudflare 缓存清除
图片被删除后,CDN 边缘还会按一年强缓存继续提供它的 /i/ 链接。配置 Cloudflare 缓存清除后,ImgYoung 在删除时主动清理边缘缓存。
在后台「设置 → 运行配置」中配置三项:
| 配置 | 位置 | 说明 |
|---|---|---|
| Cloudflare Zone ID | 「CDN 缓存清理」分组 | 站点所在 Zone 的 ID |
| Cloudflare API Token | 「CDN 缓存清理」分组 | 需要该 Zone 的 Cache Purge 权限;以主密钥加密入库,保存后不再回显 |
对外站点地址(base_url) | 「访问与链接」分组 | 清除用它拼出公开 URL,必须与 CDN 上的域名一致 |
三项齐备时分组标题旁显示「purge 已启用」,缺任一项都不清除;进程启动时也会在日志里打印当时的启用状态。配置保存即生效,不需要重启。
触发时机:一条图片引用被删除的那一刻,不论来源——后台删除(单张或批量)、S3 协议面的 DeleteObject、有效期到期回收。清除不等删除宽限,也不等渠道对象真正删掉。查重合并改指向的图片不会触发清除。
清除的 URL:<base_url>/i/<短ID>,再加上这张图实际生成过的每个衍生图对应的 ?w=<宽度>、?w=<宽度>&format=<格式>(缩放过的)或 ?format=<格式>(只转格式的)。
执行方式:作为后台任务异步执行,调用 Cloudflare 按 URL 清除缓存的接口 POST /zones/<Zone ID>/purge_cache,每次最多 100 个 URL;失败由任务队列退避重试,不影响删除本身。
不在清除范围内的:format=auto 形式、带其他查询参数或参数顺序不同的 URL,只能等 CDN 自身的缓存过期。/o/ 别名链接不需要清除:它们每次都回源确认。
302 省流量模式与 CDN
访问模式为 redirect 时,原图请求被 302 到某个允许直链、未加密且填写了公开地址的渠道,图片字节由渠道(或渠道自己的域名、CDN)直接提供,不经过你在 ImgYoung 前面的 CDN。没有这样的渠道时回退为代理。
- 302 响应一律带
Cache-Control: no-store,CDN 与浏览器都不缓存重定向本身:每次访问都回到 ImgYoung,渠道切换、删除与到期即时生效。 - 需要处理的请求(带
w/format参数,或发生了 WebP 协商)仍由 ImgYoung 处理后直接输出,不会 302。要让浏览器的原图访问也走 302,需要去掉目标格式里的webp。
已经在 ImgYoung 前面放了 CDN 时,用 proxy 模式即可:流量已由 CDN 承担。redirect 适合没有 CDN、上行带宽小的服务器,或渠道自带公开 CDN 域名(如对象存储绑定的自定义域名)的情况。
防盗链在 CDN 后的局限
ImgYoung 的 Referer 白名单只对回源请求生效:
- CDN 命中缓存的请求不回源,也就不受白名单约束;缓存键默认不含 Referer,一张图被白名单内的站点访问并缓存后,任何来源都能从 CDN 拿到;
- ImgYoung 拒绝时返回的 403 不带
Cache-Control,如果 CDN 缓存了这个 403,白名单内的访问也会被拒。
经 CDN 对外时,应在 CDN 上做防盗链(按 Referer 拦截的规则),ImgYoung 的白名单留空或只作补充。redirect 模式下渠道直链直接暴露,防盗链同样无效。