nginx需结合被动健康检查(max_fails/fail_timeout)、主动探针(nginx plus或openresty+lua模块)及proxy_next_upstream机制,才能实现websocket后端的可用性探测与自动剔除。

WebSocket 连接本身是长连接,Nginx 的 upstream 模块默认不主动探测 WebSocket 后端的可用性,也无法自动断开已建立但后端已宕机的连接。要实现真正的健康检查与自动剔除,需结合 Nginx 原生机制与合理配置,而非依赖 WebSocket 协议层的“心跳”——因为 Nginx 不解析 WebSocket 帧。
利用 Nginx 被动健康检查(fail_timeout / max_fails)
Nginx 的 upstream 支持被动式健康检查:当某节点在 max_fails 次请求中,在 fail_timeout 时间窗口内连续失败(如 502/503/504、超时、拒绝连接),则将其标记为不可用,期间不再转发新连接。
- 对 WebSocket 场景特别有效:首次 upgrade 请求失败即计入失败计数
- 需确保 proxy_pass 直接指向 upstream name(非具体 IP),且 upstream 中定义
max_fails和fail_timeout - 示例配置:
upstream ws_backend {
server 192.168.1.10:8080 max_fails=3 fail_timeout=30s;
server 192.168.1.11:8080 max_fails=3 fail_timeout=30s;
}
启用主动健康检查(需 Nginx Plus 或开源版 + lua-resty-upstream-healthcheck)
开源 Nginx 默认不带主动健康检查,但可通过以下方式补足:
-
Nginx Plus:原生支持
health_check指令,可针对 WebSocket 后端配置 HTTP 探针(如 GET /health),返回 2xx 即视为存活 - OpenResty + lua-resty-upstream-healthcheck:在 init_worker_by_lua_block 中启动异步探针,定期向后端发送 HTTP 请求检测状态,并动态更新 upstream
- 注意:探针路径必须由后端提供(例如返回
{"status":"ok"}),且不能复用 WebSocket upgrade 路径(HTTP/1.1 101 响应无法被健康检查模块识别为成功)
避免“假存活”:配合 proxy_next_upstream 处理连接中途失效
WebSocket 连接建立后若后端进程崩溃,TCP 连接可能不会立即断开(尤其未开启 keepalive 或对端未发 FIN),导致 Nginx 仍认为连接有效。此时需靠客户端重连 + Nginx 的错误传递机制兜底:
- 在 location 块中启用:
proxy_next_upstream error timeout http_502 http_503 http_504; - 当当前连接发生读写错误或超时时,Nginx 尝试将新请求(如客户端重连发起的 upgrade)转发给其他上游节点
- 搭配
proxy_next_upstream_tries 2可限制重试次数,防止雪崩
补充建议:后端配合与监控闭环
单靠 Nginx 难以覆盖所有异常场景,需前后端协同:
- 后端应在进程退出前主动从服务发现(如 Consul、Nacos)注销自身,或通过脚本修改 Nginx 配置并 reload(慎用)
- WebSocket 服务内部实现应用层心跳(如 ping/pong 帧),超时未响应则主动关闭连接,触发客户端重连
- 通过 Nginx 日志($upstream_addr、$upstream_status)或 OpenResty 的 lua_shared_dict 统计各节点失败率,对接 Prometheus 实现可视化告警











