基于TCP端口探测、基于HTTP/HTTPS请求探测、基于命令行或自定义脚本探测,其中TCP和HTTP是绝大多数负载均衡与容器平台默认采用的方式。理解这三类路径的适用边界,能帮你快速定位服务异常是出在网络层、应用层还是依赖组件上。
探测方式的核心差异与适用场景
健康检查的本质是回答两个问题:进程是否存活,以及服务是否真的能处理请求,不同的探测路径,对应着不同的信任层级。
TCP端口探测:最基础的存活判断
TCP探测是成本最低、兼容性最强的方式,探测端主动发起一次TCP握手,如果端口能完成三次握手,就判定实例健康。
- 工作路径:探测源(如负载均衡器)发送SYN包,目标端口回复SYN-ACK,连接建立,随即关闭。
- 典型使用场景:四层负载均衡(如Nginx Stream模块、LVS)、云厂商SLB的TCP检查、数据库主从切换时的端口存活判断。
- 局限:端口能连通不代表业务可用,比如Tomcat进程在但线程池已满,TCP连接依然能建立成功,但实际请求早已超时。
实操经验:在排查“健康检查显示正常但接口超时”的问题时,第一时间怀疑TCP探测的局限性,而不是业务代码本身。
HTTP/HTTPS请求探测:应用层的真实探测
HTTP探测模拟真实用户请求发到指定路径,通过状态码判断服务是否健康,这是Web服务最常见的检查方式。
- 工作路径:探测端发起GET或HEAD请求,目标返回2xx或3xx视为健康,4xx或5xx视为异常。
- 关键参数:探测路径(如
/healthz、/actuator/health)、期望状态码、超时时间、间隔时间。 - 进阶用法:要求返回JSON体中的特定字段,比如
{"status":"UP"},多用于Spring Boot Actuator等框架。
成本提示:HTTP探测比TCP多一次HTTP往返,在QPS较高的网关集群中,探测频率不宜太频繁,否则会占用业务请求的带宽。
深入解析三大类实现路径的配置逻辑
基于TCP路径的配置要点
- 探测间隔与超时:间隔建议设为业务超时时间的3倍以上,避免因慢请求误判,比如业务接口平均响应200ms,探测超时设1秒,间隔设3秒。
- 失败阈值与成功阈值:连续失败2次判定异常,连续成功2次恢复服务,这是云负载均衡的通用默认值(如简米云SLB)。
- 端口范围:探测端口必须与真实服务端口一致,内网探测建议额外开放非标准端口防止被外部扫描。
基于HTTP路径的路径设计与状态码约定
健康检查路径的设计是门学问,多数团队会单独创建一个/healthcheck接口,不做业务逻辑,只检测当前进程依赖的组件状态。
- 纯Web服务:只需返回200即可,检测进程是否僵死(僵死进程通常无法响应HTTP)。
- 有数据库依赖:接口内部执行一次
SELECT 1,但注意数据库抖动时会导致探测失败,进而摘除节点引发雪崩,行业共识是健康检查只查基础存活,深度依赖检查交给监控系统。 - 状态码约定:不要用302重定向做健康检查,容易被探测端误判为异常,404一定算失败,500算失败,401需要看探测端是否配置认证头。
基于命令行和脚本的自定义探测
当TCP与HTTP无法满足深度检查需求时,就需要自定义脚本,典型场景是检查消息队列堆积、磁盘空间、本地缓存状态等。
- 实现路径:在实例内放置一个探测脚本(如Shell、Python),负载均衡器通过SSH或Agent执行,返回0表示健康,非0表示异常。
- 常见命令示例:
- 检查磁盘:
df -h /data | grep -v Filesystem | awk '{print $5}' | cut -d% -f1,大于80返回1 - 检查进程:
pgrep -f "java.app.jar",无进程返回1 - 检查端口复用:
ss -lnt | grep 8080
- 检查磁盘:
- 适用平台:Consul的Script Check、Etcd的自定义探针、自研注册中心。
HTTPS与gRPC探测的特殊路径
- HTTPS探测:与HTTP路径一致,但需要信任证书,自签名证书场景下,负载均衡的证书校验必须关闭或配置为跳过验证,否则会一直显示异常。
- gRPC探测:基于HTTP/2协议,无法用普通HTTP GET方式检查,需要使用grpc_health_probe工具,它通过发送一个
请求,根据响应码判断健康状态。grpc.health.v1.Health/Check
容器与K8s环境中的探测配置实战
在Kubernetes中,健康检查被封装为Probe机制,这是国内运维团队最常配置的路径,K8s支持三种探针,作用各不相同:
- livenessProbe(存活探针):判断容器是否崩溃,失败会重启容器。
- readinessProbe(就绪探针):判断容器是否可接收流量,失败会从Service Endpoint中摘除。
- startupProbe(启动探针):用于慢启动容器,防止存活探针在启动期内误杀。
典型的nginx容器配置示例:
livenessProbe:
httpGet:
path: /nginx-health
port: 80
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 3
failureThreshold: 3
readinessProbe:
tcpSocket:
port: 80
periodSeconds: 5
调参经验:initialDelaySeconds需大于应用实际启动时间,否则启动期间就会触发重启。failureThreshold与periodSeconds的乘积决定了摘除节点的时间,这个时间最好是单次重启能恢复时长的1.5倍以上。
健康检查实现路径的选择对比与流量调度陷阱
| 探测方式 | 探测层级 | 发现故障速度 | 资源消耗 | 推荐场景 |
|---|---|---|---|---|
| TCP端口探测 | 传输层 | 快 | 极低 | 四层负载、数据库、缓存 |
| HTTP/HTTPS | 应用层 | 中 | 较低 | Web服务、API网关、微服务 |
| 自定义脚本 | 业务层 | 慢 | 较高 | 中间件、有状态服务 |
| gRPC | RPC层 | 快 | 低 | 微服务框架(Dubbo、gRPC) |
踩坑点一:流量瞬间倾斜
当某台实例的HTTP健康检查连续3次失败后,负载均衡会将流量全部转发给剩余节点,如果剩余节点本就接近满负荷,会导致连锁过载,业内专家建议在健康检查失败时,保留20%-30%的流量给异常节点慢速消化
,而不是直接全摘(部分云厂商支持“缓慢下线”模式)。
踩坑点二:健康检查本身引起雪崩
高并发下,健康检查请求会消耗目标实例的CPU和连接数,尤其是自定义脚本,如果脚本逻辑复杂(如执行复杂的SQL查询),会严重影响正常业务,统计显示,较大比例的线上事故都源于健康检查配置过度激进。
踩坑点三:跨地域探测的误判
总部在上海,机柜在贵州,使用默认2秒超时做TCP探测,网络RTT(往返时延)超过3秒时,健康节点会被误杀,跨地域场景下,超时时间必须大于RTT的2倍,并且建议使用HTTP/2长连接探测以降低握手成本。
常见问题与排查路径
健康检查显示正常,但请求依然超时,怎么排查?
先看健康检查的探测路径与真实业务路径是否一致,比如健康检查走/health接口,该接口不经过鉴权中间件,而真实业务走完整链路,中间件线程池已满,检查后端服务是否存在半连接状态(TCP连接已建立,但进程的accept队列已满),这种情况TCP探测无效,必须用HTTP探测。
健康检查用HTTP好还是TCP好?
如果服务是Nginx、Spring Boot等Web框架,用HTTP更好,能直接反馈应用线程池情况;如果是Redis、MySQL等基础组件,用TCP即可,它们的IO模型决定了端口连通基本等于服务可用,四层负载均衡场景下强制使用TCP,七层则优先HTTP。
健康检查频率设置多少合适?
多数情况下,间隔5秒、超时3秒、失败2次摘除是最稳妥的组合,能实现在约10秒内完成故障转移,如果追求更快的容灾(要求3秒内摘除),可以设置间隔2秒、超时1秒,但会增加一定比例的误判概率,对于数据库类有状态服务,建议间隔放宽到10秒以上,避免主从切换期间的抖动误杀。
健康检查没有银弹方案,TCP探测负责存活,HTTP探测负责可用性,脚本探测负责业务深度,在容器化时代,将三者按场景组合使用,是保障服务SLA的最优解,重点是:健康检查要简单、快速、可预期,把复杂的依赖检查留给监控告警系统,这才是成熟的架构态度。
首发原创文章,作者:王坚,如若转载,请注明出处:https://idctop.com/article/635064.html





