运维

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-ControlETagVary
/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 模式下渠道直链直接暴露,防盗链同样无效。

本页目录