nginx健康检查基于异步非阻塞事件驱动架构,通过定时器注册、非阻塞连接与事件循环处理实现;依赖ngx_http_upstream_check_module等模块支持http探针,状态默认per-worker隔离,可借openresty+lua扩展动态策略。

Nginx 本身不通过传统“事件循环”(如 Node.js 或 Python asyncio 那样的用户态协作式循环)实现健康检查,而是基于其核心的 异步非阻塞事件驱动架构,结合定时器机制与连接状态管理,在 worker 进程中完成对后端服务器的主动探测与状态维护。
健康检查依赖 Nginx 的事件驱动模型而非独立事件循环
Nginx 的每个 worker 进程运行在一个单线程、事件驱动的主循环中(通常基于 epoll/kqueue/select),该循环持续监听 socket 读写就绪、定时器超时等事件。健康检查任务被注册为周期性定时器事件,当触发时,worker 不会阻塞等待响应,而是:
- 发起一个非阻塞 TCP 连接(或发送 HTTP/HTTPS 探针)
- 将该连接加入事件监听集合,后续由同一事件循环处理其可读/可写/错误状态
- 根据响应内容、超时、TCP 状态等判断后端是否存活,并更新 upstream 中对应 server 的状态标记(如
down、checking、up)
ngx_http_upstream_check_module 是典型实现载体
官方 Nginx 不内置高级健康检查(如 HTTP 状态码校验、自定义 body 匹配),需依赖第三方模块 ngx_http_upstream_check_module(常随 Tengine 或 OpenResty 发行版集成)。它扩展了 upstream 指令,支持:
-
check interval=3 rise=2 fall=5 timeout=1 type=http:每 3 秒发一次 HTTP 探针,连续 2 次成功则恢复服务,连续 5 次失败则标记为 down -
check_http_send "GET /health HTTP/1.0\r\n\r\n"和check_http_expect_alive http_2xx http_3xx:控制请求内容与判定逻辑 - 所有探测由 worker 内部调度,复用已有的连接池与事件分发机制,无额外线程或进程开销
状态同步与共享限制需注意
由于每个 worker 独立运行事件循环,健康检查状态默认不跨 worker 共享。这意味着:
- 不同 worker 可能对同一后端持有不同状态(如一个认为 up,另一个认为 down)
- 解决方式包括启用
shared memory zone(模块需支持)或依赖外部协调(如 consul + nginx-upsync-module) - 官方 stream/http 模块的简单
max_fails/fail_timeout是 per-worker 统计,轻量但粒度粗(仅基于真实请求失败,非主动探测)
替代方案:OpenResty + Lua 实现更灵活的健康检查逻辑
若需动态策略(如按负载调整探测频率、调用外部 API 校验、熔断降级联动),可借助 OpenResty:
- 在
init_worker_by_lua_block中启动后台定时器(ngx.timer.at) - 使用
resty.http发起异步探针,回调中更新 shared dict 状态 - 在
balancer_by_lua_block中读取最新状态,影响负载均衡决策 - 整个过程仍在 Nginx 事件循环内完成,保持高性能与低资源占用










