关键是要将真正影响图片内容的分辨率参数(如w、h、dpr、fit、fm等)纳入proxy_cache_key,剔除utm_source等无关参数,通过map指令安全提取并构造精简缓存键,确保不同分辨率命中独立缓存项。

要让不同分辨率的图片各自拥有独立缓存项,关键不是把所有请求参数照单全收,而是只把真正影响图片内容输出的变量纳入 proxy_cache_key —— 分辨率就是那个核心变量,其他如跟踪参数、设备标识、语言偏好等若不参与图片生成逻辑,就必须剔除。
提取真实影响图片输出的分辨率参数
多数图片服务(如 Imgix、Cloudinary 或自建缩略图服务)通过 query 参数控制尺寸,例如 ?w=320&h=240、&fit=cover&dpr=2。这些参数直接决定后端返回哪张图,必须保留在 key 中;而 utm_source、ref、_ga 等纯埋点字段则会制造大量无效缓存碎片。
- 用
map指令安全提取关键尺寸参数,避免在proxy_cache_key行内写正则:
map $args $cache_res {
~(w=\d+&h=\d+|h=\d+&w=\d+|w=\d+|h=\d+|dpr=[1-4]|fit=(cover|contain|crop)) ;
default "";
}
- 若服务同时支持 URL 路径式分辨率(如
/img/320x240/photo.jpg),可用map $uri $cache_path_res { ~^/img/(\d+x\d+)/.*$ $1; }提取 - 确保提取结果稳定:不带空格、无非法字符,长度可控(如
dpr=2比完整$http_user_agent更轻量也更精准)
构造干净、可区分、无冗余的缓存键
最终 key 应只包含「协议 + 域名 + 图片路径 + 分辨率标识」,排除所有无关干扰:
- 基础结构推荐:
proxy_cache_key "$scheme$host$uri|$cache_res"; - 若同一张原图还支持格式转换(如
&fm=webp),需一并纳入:~(fm=(webp|avif|jxl)|q=\d+) $1;,再拼入 key - 绝对不要用
$args全量,否则?w=320&h=240&utm_medium=banner和?w=320&h=240&fbclid=xxx会被视为两个 key,浪费 90% 缓存空间
配合 cache_bypass 实现开发与灰度验证
分辨率缓存上线后,需保留快速绕过能力,用于调试或定向测试:
- 加参直通后端:
proxy_cache_bypass $arg_nocache;,访问?nocache=1即跳过缓存 - 灰度验证新尺寸逻辑时,可按 Header 控制:
proxy_cache_bypass $http_x_img_test;,仅对带特定 header 的请求不缓存 - 注意:若图片服务本身已做 ETag 或 Last-Modified 校验,建议同步配置
proxy_cache_revalidate on;,避免 stale 内容长期滞留
验证是否真正生效
改完配置不能只看 Nginx 启动成功,要确认缓存行为符合预期:
- 响应头中必须有
add_header X-Cache-Status $upstream_cache_status;,用curl -I查看连续请求是否从MISS变为HIT - 对比不同分辨率请求的缓存路径:
curl -I https://example.com/photo.jpg?w=320和curl -I https://example.com/photo.jpg?w=768,两者X-Cache-Status应互不干扰 - 检查缓存目录实际文件:
find /var/cache/nginx/image_cache -name "*photo.jpg*" | head -5,应看到含不同w=或dpr=片段的子目录,而非一堆随机哈希


















