Consul 服务发现驱动动态 upstream 更新:NJS 通过 shared dictionary 缓存健康节点,定时拉取并热更新;启动全量加载、后台轮询比对版本号触发刷新;结合失败计数与自动重试实现优雅剔除。

Consul 服务发现驱动动态 upstream 更新
Consul 作为服务注册与健康检查中枢,天然支持服务实例的自动注册/注销和实时健康状态同步。NJS(NGINX JavaScript)可借助 consul kv watch 或 consul catalog services 接口,定时拉取当前健康的后端节点列表,避免依赖传统 reload 触发配置变更。
NJS 脚本内构建可热更新的 upstream 变量
NJS 不直接操作 nginx.conf 的 upstream 块,而是通过 shared dictionary 存储节点列表,并在 js_set 或 js_var 中动态解析目标地址。关键点:
- 使用
ngx.shared.upstream_nodes字典缓存 JSON 格式节点数组,带 TTL 避免脏数据 - 在
js_set $backend中调用函数:先查字典 → 若过期或空则触发一次 Consul API 请求 → 解析响应并更新字典 → 返回选中的 host:port - 配合
proxy_pass http://$backend实现无 reload 转发
Consul Watch + NJS 定时同步机制
为降低 Consul 查询压力并保证时效性,采用混合策略:
- 启动时由 NJS 主动拉取全量服务列表并写入 shared dict
- 后台启动
setInterval定时任务(如 5s 一次),对比本地版本号或 MD5 与 Consul KV 中的upstream/version是否一致,仅变更时刷新节点 - Consul 端可通过
consul watch监听 service 变更,自动写入 KV 触发 NJS 检测逻辑(非必须,可简化为轮询)
健康探测与优雅剔除节点
Consul 自身健康检查已过滤不健康实例,但 NJS 层仍需应对网络抖动导致的临时不可达:
- 在 NJS 函数中对每个候选节点记录失败次数和最后失败时间
- 当连续失败超过阈值(如 3 次),临时移出可用列表,10 秒后自动重试
- 配合 NGINX 的
proxy_next_upstream error timeout,形成双层容错











