Nginx 无法直接用 NJS 动态开关 proxy_cache 写入,但可通过 NJS 生成变量(如 $njs_cache_control),再由 proxy_cache_bypass 和 proxy_no_cache 联动实现请求级缓存绕过;需配合 os.loadavg() 判断负载、启用 proxy_buffering、确保上游缓存头有效,并合并登录态等其他规则。

不能直接用 NJS 动态开关 proxy_cache 的写入,因为 NJS 运行在请求处理阶段(如 access_by_lua* 或 NJS 的 js_access),而缓存写入决策发生在 proxy_buffering 后、响应发送前的更晚阶段,NJS 无法中途“撤回”已进入缓存流程的响应。
真正可行的替代路径:用 NJS 控制 bypass/no_cache 变量
NJS 不参与缓存区读写逻辑,但可以生成一个运行时变量(比如 $njs_cache_control),再通过 proxy_cache_bypass 和 proxy_no_cache 让特定请求绕过缓存——这等效于“动态禁用缓存写入”。关键在于:不靠 NJS 改指令,而是靠它算出开关信号。
- 在
http块中定义一个占位 map,例如:map "" $njs_cache_control { default ""; }(初始为空,供后续覆盖) - 在
location中调用 NJS 函数:js_set $njs_cache_control njs_check_load; - 然后绑定到缓存控制指令:
proxy_cache_bypass $njs_cache_control;<br>proxy_no_cache $njs_cache_control;
如何用 NJS 获取并判断系统负载
NJS 本身不提供 /proc/loadavg 读取能力,但可通过 os.loadavg()(需 Nginx ≥ 1.25.3 + 启用 --with-compat)获取 1/5/15 分钟平均负载。典型判断逻辑:
⚠️ 已弃用 — 该技能已拆分为两个独立技能,以提升模块化程度:**webchat-https-proxy**(HTTPS/WSS 反向代理)和 **webchat-voi...**
- 若 1 分钟负载 ≥ 8(假设是 8 核机器),返回非空值(如
"high"),触发 bypass/no_cache - 否则返回空字符串,正常走缓存
- 示例函数(放在
js_preload或js_import文件中):function njs_check_load(r) {<br> const load = os.loadavg();<br> if (load && load[0] >= 8) return "1";<br> return "";<br>}
必须同步调整的配套项
仅靠 NJS 判断还不够,要让整个链路生效,还需确认以下三点:
-
启用
proxy_buffering on:这是proxy_no_cache生效的前提,否则响应体未缓冲就直接流式转发,缓存逻辑根本不介入 -
确保上游响应带明确缓存头:如
Cache-Control: public, max-age=300,否则 Nginx 默认不缓存(尤其对 200 响应) -
避免与 cookie/session 冲突:如果已有基于
$cookie_session的 map 规则,需合并逻辑,例如在 NJS 函数里一并检查登录态和负载,统一输出控制值
验证是否按负载生效
不用猜,用两个命令快速确认:
- 模拟高负载后发请求:
curl -I http://your.site/api/data | grep X-Proxy-Cache→ 应看到X-Proxy-Cache: BYPASS - 查缓存目录是否无新增文件:
find /var/cache/nginx -name "*data*" -mmin -1→ 高负载期间应无匹配结果

















