lua-resty-checkups通过融合主动探测与被动观测实现多维动态健康评分,支持灰度恢复、软下线及实时权重调整,避免单点误判,使Nginx真正理解后端“卡、崩、慢”的差异。

nginx 本身不提供开箱即用的智能健康状态管理,但通过 lua-resty-checkups(注意:不是 lua-resty-healthcheck)可实现基于响应内容、失败率、请求延迟等多维指标的动态节点状态判定。该模块专为 OpenResty 设计,支持共享内存计数、自定义探测逻辑与灰度恢复,比原生被动检查更及时,比纯主动探测更抗误判。
为什么选 lua-resty-checkups 而非其他方案
它由 OpenResty 官方生态维护,轻量、无外部依赖,且设计上明确区分“主动探测”与“被动观测”两类信号:
- 主动探测:定期发 HEAD/GET 请求到 /health,解析响应体或状态码
- 被动观测:拦截真实业务请求,统计 5xx 比例、超时次数、P95 延迟突增等
- 两者结果在 shared dict 中融合加权,避免单点误判(例如某次网络抖动导致一次 504 不直接下线)
- 支持“软下线”——节点标记为 unhealthy 后,仍按 5% 流量试探,1 分钟内连续 3 次成功则自动恢复全量
基础部署与初始化配置
需使用 OpenResty(≥1.21.4.2),并确保已安装 lua-resty-checkups(推荐用 opm 安装):
opm get leafo/lua-resty-checkups
在 nginx.conf 的 http 块中声明共享字典和初始化逻辑:
lua_shared_dict checkups_status 10m;
init_by_lua_block {
local checkups = require "resty.checkups"
checkups.init({
dict = "checkups_status",
default_check_interval = 5, -- 默认探测间隔(秒)
default_fail_timeout = 60, -- 节点被踢出后等待重试时间
})
}
定义带多级健康策略的 upstream
以下配置对两个后端服务启用混合检查:
upstream payment_api {
server 10.0.1.10:8080;
server 10.0.1.11:8080;
<pre class="brush:php;toolbar:false;"># 启用 lua-resty-checkups 管理
balancer_by_lua_block {
local checkups = require "resty.checkups"
local checker = checkups.new("payment_api")
-- 添加目标节点(支持域名、IP+端口、Unix socket)
checker:add_target("10.0.1.10", 8080)
checker:add_target("10.0.1.11", 8080)
-- 主动探测:每 3 秒请求 /health,要求返回 JSON { "status": "ok" }
checker:set_active_check({
type = "http",
http_path = "/health",
http_expect_body = '"status":"ok"',
interval = 3,
timeout = 1.5,
healthy = { successes = 2 },
unhealthy = { failures = 4 },
})
-- 被动观测:对真实请求采样,若 1 分钟内 5xx ≥ 15% 或平均延迟 > 800ms,则降权
checker:set_passive_observation({
http_5xx_ratio_threshold = 0.15,
avg_latency_ms_threshold = 800,
window_seconds = 60,
})
-- 执行负载选择(自动跳过 unhealthy 节点,支持 backup fallback)
local ok, err = checker:balance()
if not ok then
ngx.log(ngx.WARN, "checkups balance failed: ", err)
-- 可 fallback 到静态 backup 或返回 503
ngx.exit(503)
end
}
}
关键点说明:
-
http_expect_body支持正则或子串匹配,比仅看状态码更能反映业务层存活 - 被动观测不阻塞请求,仅异步更新节点权重;当某节点被多次标记为 slow 或 error,其 weight 自动降至 1(默认为 100)
-
checker:balance()替代了原生 round-robin,会读取实时健康分排序节点
运行时监控与人工干预接口
暴露一个内部 location,供运维查看和临时干预:
location /checkups/status {
internal;
content_by_lua_block {
local checkups = require "resty.checkups"
local status = checkups.get_status("payment_api")
ngx.say("Upstream: payment_api\n")
for _, node in ipairs(status.nodes) do
ngx.say(string.format(
" %s:%d -> health=%s, weight=%d, last_check=%s, errors_1m=%d\n",
node.host, node.port,
node.healthy and "up" or "down",
node.weight,
os.date("%H:%M:%S", node.last_check_time),
node.passive_errors_1m
))
end
}
}
还可配合 Prometheus exporter 或简单 curl 查看:
curl http://127.0.0.1/checkups/status
如需手动下线某节点(例如发布前预摘流):
location /checkups/down {
internal;
content_by_lua_block {
local checkups = require "resty.checkups"
checkups.down_node("payment_api", "10.0.1.11", 8080, 300) -- 下线 5 分钟
ngx.say("10.0.1.11:8080 down for 300s")
}
}
不复杂但容易忽略:lua-resty-checkups 的价值不在“能做健康检查”,而在于把“节点是否可用”从布尔值升级为带上下文的连续评分——它让 Nginx 真正理解后端是“卡了”、“崩了”还是“只是慢了一点”。











