nginx+tomcat环境下,nginx对后端Tomcat实例的健康检查机制
2026/5/25 15:19:59 网站建设 项目流程

Nginx 对后端 Tomcat 的健康检查分为被动检查(开源版默认)和主动检查(商业版或通过第三方模块实现)两种。


一、被动健康检查(开源 Nginx 原生支持)

原理:Nginx 在转发请求时,如果发现某个后端节点出现问题,会将其标记为不可用,并在fail_timeout时间内不再转发请求给它。

配置示例

upstream tomcat_cluster { 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 max_fails=3 fail_timeout=30s; } server { listen 80; location / { proxy_pass http://tomcat_cluster; proxy_next_upstream error timeout invalid_header http_500 http_502 http_503; } }

参数说明

参数说明
max_fails=3允许的最大失败次数
fail_timeout=30s失败超时时间。30秒内如果失败3次,则标记为不可用,后续30秒内不再转发请求
proxy_next_upstream定义什么情况下认为"失败",会尝试下一个节点

proxy_next_upstream可配置的状态

状态说明
error连接后端时发生网络错误
timeout连接或读取后端超时
invalid_header后端返回无效的响应头
http_500后端返回500错误
http_502后端返回502错误
http_503后端返回503错误
http_504后端返回504错误
off关闭重试机制

被动检查的局限性

  1. 必须有用户请求才会触发检查。如果节点已经坏了但没人访问,Nginx 不会主动发现
  2. 故障节点恢复后,不会自动回归。需要等待fail_timeout时间后,再接收少量请求"试探",成功后才逐步恢复流量
  3. 不能提前摘除即将出问题的节点(如CPU飙高、Full GC频繁)

二、主动健康检查(Nginx Plus 或 nginx-upsync 模块)

原理:Nginx 主动向后端节点发送探测请求(如 HTTP GET /health),根据响应判断节点健康状态,自动摘除或恢复。

Nginx Plus 配置示例(商业版)

upstream tomcat_cluster { zone upstream_zone 64k; server 192.168.1.10:8080; server 192.168.1.11:8080; health_check interval=5s fails=3 passes=2 uri=/health match=health_ok; } match health_ok { status 200; header Content-Type = application/json; body ~ "status.*UP"; }

参数说明

参数说明
interval=5s每5秒检查一次
fails=3连续3次失败,标记为不可用
passes=2连续2次成功,标记为可用
uri=/health检查后端哪个接口
match匹配规则(状态码、响应头、响应体)

开源替代方案:nginx-upsync + consul

社区常用的方案是使用nginx-upsync模块结合consul实现动态主动健康检查。


三、Tomcat 端需要提供的健康检查接口

无论用哪种方式,Tomcat 都需要提供一个健康的检查接口(例如/health),返回当前节点的健康状态。

方案1:Spring Boot Actuator(标准做法)

# application.ymlmanagement:endpoints:web:exposure:include:health,readyendpoint:health:show-details:alwayshealth:db:enabled:trueredis:enabled:true

访问/actuator/health返回:

{"status":"UP","components":{"db":{"status":"UP"},"diskSpace":{"status":"UP"},"redis":{"status":"UP"}}}

方案2:自定义专用健康检查接口(更精细)

@RestControllerpublicclassHealthController{@AutowiredprivateDataSourcedataSource;@AutowiredprivateRedisTemplateredisTemplate;@GetMapping("/health")publicResponseEntity<Map<String,Object>>health(){Map<String,Object>status=newHashMap<>();// 检查数据库连接try{dataSource.getConnection().close();status.put("database","UP");}catch(Exceptione){status.put("database","DOWN: "+e.getMessage());}// 检查Redis连接try{redisTemplate.getConnectionFactory().getConnection().ping();status.put("redis","UP");}catch(Exceptione){status.put("redis","DOWN");}// 判断整体状态booleanisHealthy=status.values().stream().allMatch(v->v.toString().startsWith("UP"));returnResponseEntity.status(isHealthy?HttpStatus.OK:HttpStatus.SERVICE_UNAVAILABLE).body(status);}}

四、生产环境最佳实践:主被动结合

检查方式作用实现位置
被动检查兜底,防止主动检查漏掉的故障Nginxmax_fails+proxy_next_upstream
主动检查提前发现故障,快速摘除Nginx Plus 或nginx-upsync
应用层健康接口提供真实的健康状态(不仅进程存活,还要检查依赖)Tomcat/health接口
监控告警节点频繁抖动时报警,人工介入Zabbix/Prometheus

配置建议

upstream tomcat_cluster { # 被动检查:兜底 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 或 upsync 模块 # health_check interval=5s fails=3 passes=2 uri=/health; keepalive 32; # 保持连接池 } location / { proxy_pass http://tomcat_cluster; proxy_next_upstream error timeout http_500 http_502 http_503; proxy_next_upstream_tries 2; # 最多重试2次 proxy_connect_timeout 3s; # 连接超时3秒 proxy_read_timeout 30s; # 读取超时30秒 }

五、常见问题排查

现象可能原因解决
后端已宕机,Nginx 还在转发被动检查未触发(无请求进来)增加主动健康检查
健康检查总是失败/health接口没实现或返回非200curl -v http://tomcat:8080/health手动测试
节点一直在"抖动"(频繁被摘除和恢复)健康检查超时时间太短,或后端压力大响应慢调整fail_timeoutinterval,优化后端
重启 Tomcat 后流量不恢复fail_timeout未过,或被动检查还没尝试配置主动健康检查,或缩短fail_timeout

六、一句话总结

Nginx 开源版默认只支持被动健康检查(靠转发失败来发现故障),生产环境建议配合主动健康检查(Nginx Plus 或nginx-upsync模块),同时让 Tomcat 提供/health接口,检查数据库、Redis 等依赖的真实状态,实现精准的节点摘除和恢复。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询