为什么负载均衡需要健康检查
负载均衡的核心任务是把请求分发到多台后端服务器,但如果某台服务器挂了,Nginx还往它发请求,用户就只能收到502错误。健康检查就是解决这个问题的——让Nginx自动识别故障节点,停止往它转发流量,等它恢复后再重新纳入集群。
Nginx的健康检查分两种:被动健康检查(开源版自带)和主动健康检查(需要第三方模块或商业版)。两种各有优缺点,下面逐个讲清楚。
一、被动健康检查:Nginx自带的max_fails和fail_timeout
被动检查的原理很简单:Nginx正常转发请求给后端服务器,如果后端返回错误或超时,Nginx就记录一次失败。失败次数达到阈值后,暂时不再往这台服务器发请求。
1.1 核心参数说明
在upstream块里给每个server配置两个参数:
- max_fails:最大失败次数,默认值是1。超过这个次数,Nginx标记该服务器为不可用
- fail_timeout:失败后暂停转发的时间窗口,默认10秒。在这个时间内不往故障节点发请求,过了之后会再尝试一次
1.2 配置示例
upstream 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;
server 192.168.1.12:8080 backup;
}
server {
listen 80;
location / {
proxy_pass http://backend;
proxy_next_upstream error timeout http_502 http_503 http_504;
}
}
这个配置的意思是:每台服务器连续3次请求失败后,标记为不可用,30秒内不再转发请求给它。proxy_next_upstream指定遇到哪些错误时自动切换到下一台服务器。
1.3 被动检查的缺点
- 只有真实用户请求到了故障节点才会触发检测,第一波用户还是会遇到错误
- fail_timeout到期后只尝试一次,如果刚好又失败,又要等一个周期
- 无法定期主动探测服务器状态,故障发现滞后
- 没有健康状态的查看页面,运维不直观
二、主动健康检查:nginx_upstream_check_module
主动检查的思路是:Nginx按固定时间间隔主动向后端发探测请求,根据响应判断服务器是否健康。故障节点在用户请求到来之前就被摘除,真正实现零误差转发。
开源版Nginx没有内置主动检查模块,最常用的是淘宝团队开发的nginx_upstream_check_module。需要重新编译Nginx加入这个模块。
2.1 编译安装
# 安装依赖 yum install -y gcc gcc-c++ pcre-devel openssl-devel patch # 下载Nginx源码和模块 wget http://nginx.org/download/nginx-1.24.0.tar.gz wget https://github.com/yaoweibin/nginx_upstream_check_module/archive/master.zip # 解压 tar xf nginx-1.24.0.tar.gz unzip master.zip # 打补丁(进入Nginx源码目录) cd nginx-1.24.0 patch -p1 < ../nginx_upstream_check_module-master/check_1.20.1+.patch # 编译安装 ./configure --add-module=../nginx_upstream_check_module-master make && make install
注意:补丁版本要跟Nginx版本匹配,check_1.20.1+.patch适用于Nginx 1.20.1及以上版本。
2.2 配置示例
upstream backend {
server 192.168.1.10:8080;
server 192.168.1.11:8080;
# 主动健康检查配置
check interval=3000 rise=2 fall=3 timeout=1000 type=http;
check_http_send "HEAD /health HTTP/1.0\r\n\r\n";
check_http_expect_alive http_2xx http_3xx;
}
server {
listen 80;
location / {
proxy_pass http://backend;
}
# 健康状态查看页面
location /status {
check_status;
access_log off;
allow 192.168.1.0/24;
deny all;
}
}
2.3 参数详解
- interval:检测间隔,单位毫秒。3000表示每3秒检测一次
- rise:连续成功次数。rise=2表示连续2次检测成功后标记为健康,恢复转发
- fall:连续失败次数。fall=3表示连续3次检测失败后标记为故障,停止转发
- timeout:每次检测的超时时间,单位毫秒
- type:检测类型,支持tcp、http、ssl、ajp等
- check_http_send:HTTP检测时发送的请求内容
- check_http_expect_alive:认为健康的HTTP状态码
2.4 健康状态页面
配置了check_status后,访问/status路径可以看到每台后端服务器的健康状态,包括:
- 服务器地址和端口
- 当前状态(up/down)
- 最近一次检测时间和结果
- 连续成功/失败次数
这个页面是运维排查问题的重要入口,建议只允许内网访问。
三、Nginx Plus商业版的健康检查
如果用的是Nginx Plus(商业版),内置了health_check指令,不需要额外编译模块:
upstream backend {
server 192.168.1.10:8080;
server 192.168.1.11:8080;
}
server {
location / {
proxy_pass http://backend;
health_check interval=5s fails=3 passes=2 uri=/health;
}
}
商业版的优势是配置简洁、官方维护、支持更丰富的检测条件(比如匹配响应体内容)。但需要付费,适合企业生产环境。
四、两种方案对比
| 特性 | 被动检查(max_fails) | 主动检查(check模块) |
|---|---|---|
| 是否需要编译 | 不需要 | 需要重新编译 |
| 故障发现速度 | 慢,依赖真实请求 | 快,定期主动探测 |
| 状态查看页面 | 没有 | 有(check_status) |
| 适用场景 | 小规模、对延迟不敏感 | 生产环境、对可用性要求高 |
| 维护成本 | 低 | 中等(需维护编译版本) |
五、实战建议
- 小型站点或测试环境,用被动检查就够了,配置简单零依赖
- 生产环境一定要用主动检查,故障节点零延迟摘除,用户体验好
- 健康检查的间隔别太短(1秒以下),否则后端压力大;也别太长(超过10秒),发现故障慢
- rise设2比设1更稳,避免偶发超时误判;fall设3同理
- 后端应用一定要提供/health接口,返回200就表示健康,别用HEAD请求去检测复杂业务路径
- check_status页面务必限制内网访问,别暴露给公网
- 如果不想重新编译Nginx,可以考虑用Nginx Plus或外部监控工具(如Consul+健康检查脚本)配合实现
六、常见问题
Q:max_fails=0是什么意思?
表示不统计失败次数,即永远不标记服务器为不可用。一般不建议这样设置,除非你有外部监控系统单独处理故障切换。
Q:主动检查模块打补丁失败了怎么办?
补丁版本必须跟Nginx版本对应。先确认Nginx版本,然后到模块的GitHub页面查看支持的补丁文件列表。版本不匹配就换个补丁或换个Nginx版本。
Q:配置了check后Nginx启动报错?
最常见的错误是check指令写在server块而不是upstream块里。check相关指令的位置:check写在upstream块,check_status写在server块的location里。
Q:后端服务器恢复了但流量还是没回来?
检查rise参数是否设置过大。rise=2需要连续2次检测成功才恢复,如果检测间隔是3秒,恢复需要6秒。可以适当减小rise或缩短interval。
相关文章
版权声明
本文仅代表个人观点。
本文系AI辅助作者原创,未经许可,转载请保留原文链接。

发表评论