Nginx + NJS 可通过 shared dict 实时统计上游错误码实现秒级动态摘机,结合 js_content 与 error_page 触发判定逻辑,并需区分 upstream_status 与 status 避免误剔。

在 Nginx + NJS 环境中,可以通过 njs 模块编写轻量、可复用的状态控制逻辑,动态决定是否将上游节点从健康检查池中剔除(即“动态摘机”),尤其适用于对特定错误码(如 502、503、504 或自定义业务错误码)进行精细化响应处理。
理解 NJS 与 upstream 的交互机制
NJS 本身不能直接修改 upstream 配置块,但可通过以下方式间接实现“动态剔除”效果:
- 使用
proxy_next_upstream配合proxy_next_upstream_tries和proxy_next_upstream_timeout控制重试行为; - 在
js_content或js_set中捕获响应状态,结合proxy_intercept_errors on+ 自定义 error_page,触发 JS 逻辑判断是否应跳过当前 upstream; - 更推荐的方式:利用
js_preload加载自定义模块,在js_filter(NJS 0.8.0+ 支持)或js_content中调用ngx.fetch()或ngx.redirect()实现请求重定向/降级,绕过异常 upstream; - 若需持久化“剔除状态”,需配合外部存储(如 shared dict、Redis)记录节点故障时间与次数,NJS 负责读写和决策。
编写 NJS 函数识别并响应特定错误码
在 /etc/nginx/njs/error_handler.js 中定义核心逻辑:
http
- 在定时器(
js_periodic,NJS 0.8.2+)中定期扫描 shared dict,对超时未更新的故障条目自动清理; - 暴露
/nginx_status/faillog接口,用js_content返回当前各 upstream 故障计数,便于监控告警; - 对关键接口启用
proxy_cache_use_stale error timeout updating,提升容错体验; - 日志中结构化输出
$upstream_addr $upstream_status $bypass_flag,便于 ELK 分析剔除根因。
不复杂但容易忽略的是:NJS 的 shared dict 是进程级而非全局,多 worker 场景下需确保逻辑幂等;错误码判断必须区分 upstream_status(上游返回)和 status(Nginx 自身状态),否则会把本机超时也纳入剔除逻辑。











