nginx原生不支持直接接管proxy_cache命中逻辑,但可通过openresty的lua模块在关键阶段前置干预:用set_by_lua_block动态控制proxy_no_cache/proxy_cache_bypass、重写proxy_cache_key、用lrucache替代部分缓存、拦截修改响应头以影响缓存行为。

直接接管 proxy_cache 的命中逻辑,Nginx 原生不支持——它没有开放缓存查找前的钩子。但你可以用 Lua(通过 OpenResty)在关键阶段“绕过”或“模拟”命中行为,实现等效控制:比如跳过缓存、强制回源、动态改写缓存键、甚至用共享字典自建轻量缓存层。核心不是修改 proxy_cache 内部,而是前置干预请求流。
用 set_by_lua_block 动态决定是否走缓存
proxy_cache 是否生效,取决于 location 中是否启用 proxy_cache 指令,以及 proxy_no_cache / proxy_cache_bypass 的布尔值。Lua 可以计算这些变量:
- 在 location 中写 set_by_lua_block,根据 $http_user_agent、$arg_debug、$cookie_auth 等判断业务意图
- 把结果赋给自定义变量,例如 set $skip_cache 0;命中调试条件时设为 1
- 配置 proxy_no_cache $skip_cache 和 proxy_cache_bypass $skip_cache ——两者都为 1 时,既不读缓存也不存缓存
用 Lua 重写 proxy_cache_key 实现细粒度区分
proxy_cache_key 是缓存命中的唯一依据,默认不包含 Cookie 或部分 header。若需按用户身份、灰度标签、设备类型缓存不同版本,不能只靠静态字符串:
安全更新和维护 CLI Proxy API(CPA)部署与配置。用于 CPA 镜像升级、配置变更、认证目录兼容修复、上线验证与回滚。适用于用户提到“CPA 更新/升级/配置改了/容器重建/回滚”等场景。
- 用 set_by_lua_block 构造带业务维度的 key 字符串,如 "$scheme|$host|$uri|$cookie_uid|$arg_abtest"
- 将结果存入变量 $my_cache_key,再在 location 中写 proxy_cache_key $my_cache_key
- 注意:该变量必须在 proxy_cache_key 指令所在作用域内已定义,且不能含非法字符(建议用下划线/短横线分隔)
用 balancer_by_lua_block + lua-resty-lrucache 替代部分 proxy_cache
当 proxy_cache 颗粒太粗(比如整个路径共用一个缓存区)、或需要毫秒级 TTL、或要合并多个后端响应做缓存决策时,可局部绕过 proxy_cache:
- 在 init_by_lua_block 中预热 lrucache:new(1000),存于全局变量
- 在 rewrite_by_lua_block 或 access_by_lua_block 中,用请求特征生成 cache_key,查 lrucache
- 若命中,用 ngx.exec() 或 ngx.redirect() 提前返回;未命中则继续走 proxy_pass
- 后端响应返回后,在 header_filter_by_lua_block 中调用 lrucache:set() 存入,TTL 可精确到秒
拦截并修改缓存响应头,影响 proxy_cache 行为
Nginx 默认会遵循后端返回的 Cache-Control、Expires、Set-Cookie 等响应头,可能意外禁用缓存。Lua 可在响应发出前动态清理或覆盖:
- 在 header_filter_by_lua_block 中检查 ngx.var.upstream_http_cache_control
- 对特定接口(如 /api/v2/user),强制清除 Set-Cookie:ngx.header["Set-Cookie"] = nil
- 或统一注入缓存策略:ngx.header["X-Cache-By"] = "lua-override",便于监控
- 注意:proxy_ignore_headers 已设置的头不会进入 ngx.var.upstream_http_*,需提前在 proxy_ignore_headers 中移除对应项










