核心是用map将ua归一化为desktop/mobile/tablet等稳定类型,再将其加入proxy_cache_key(如"$scheme$request_method$host$request_uri$device_type"),并确保缓存区启用、无意外绕过,最后通过curl和日志验证识别与命中效果。

在 Nginx 中实现按客户端设备类型(如 PC、手机、平板)区分缓存,核心是修改 proxy_cache_key(或 fastcgi_cache_key 等),把能标识设备类型的变量加入其中。关键在于:先准确识别设备类型,再将其稳定、可预测地映射为简短标识(如 desktop、mobile),最后拼入缓存键。
识别设备类型:用 $http_user_agent 做基础判断
Nginx 本身不内置“设备类型”变量,需基于 $http_user_agent 手动判断。推荐用 map 指令预定义映射,高效且可复用:
map $http_user_agent $device_type {
default desktop;
~*[Tt]ablet tablet;
~*[Mm]obile mobile;
~*Android mobile;
~*iPhone mobile;
~*iPad tablet;
~*Windows.*Phone mobile;
}说明:
- map 块必须放在 http 块中(不能在 server 或 location 内);
- 正则匹配区分大小写(~* 表示不区分),顺序重要,更具体的规则(如 iPad)建议放在通用规则(如 Mobile)之前;
- default 是兜底值,确保所有请求都有值,避免缓存键为空导致异常。
构造带设备类型的缓存键
在需要缓存的 location 块中,将 $device_type 加入 proxy_cache_key:
proxy_cache_key "$scheme$request_method$host$request_uri$device_type";
说明:
- 保持原有缓存键结构(如 scheme + method + host + uri)是基础,保证同一 URL 在不同设备下生成不同 key;
- 不要只用 $device_type,否则不同 URL 可能因设备相同而误命中;
- 若使用了请求参数(如分页、排序),建议加上 $args(即 $scheme$request_method$host$request_uri$device_type$args),否则带参数的请求可能被错误合并缓存。
确保缓存策略支持多键差异
仅改 key 不够,还需确认缓存配置允许不同 key 存为独立条目:
-
缓存区已启用:确认
proxy_cache指向一个已定义的缓存区(如proxy_cache my_cache;); -
忽略部分头不影响区分:如果用了
proxy_cache_bypass或proxy_no_cache,检查它们是否意外绕过缓存(例如根据$cookie或$arg判断),避免设备类型生效前就被跳过; -
后端响应头兼容:若后端返回了
Cache-Control: private或Vary: User-Agent,Nginx 默认不会缓存。可加proxy_ignore_headers Cache-Control;或proxy_hide_header Vary;(谨慎使用,需确认业务允许)。
验证与调试技巧
上线前快速验证是否生效:
- 用
curl -H "User-Agent: Mozilla/5.0 (iPhone..." http://yoursite.com和 PC 的 UA 分别请求,观察响应头中的X-Cache(如自定义为HIT/MIS)是否各自首次为MIS、二次为HIT; - 开启
log_format记录$device_type和$upstream_cache_status,查日志确认设备识别与缓存状态匹配; - 临时在 response header 中添加
add_header X-Device-Type $device_type;,直观看识别结果。











