健康检查探测方式的核心路径分为传输层探测和应用层探测两大类,前者以TCP端口连通性为主,后者以HTTP/HTTPS请求返回值为主,两者可组合覆盖绝大多数业务场景。
健康检查探测方式有哪些?先分清四种基础协议路径
健康检查的原理并不复杂,本质上是让一台调度设备或监控程序,按固定频率向目标服务发送探测请求,再根据返回结果判断服务是否健康,目前各类负载均衡、容器编排平台和监控系统,底层实现都绕不开以下四种路径。
TCP端口探测:最朴素的连通性检查
TCP探测的实现路径非常直观:探测端向目标IP的指定端口发起三次握手,握手成功就判定服务存活,失败则标记为不健康,这种方式的优点是开销极小、响应速度快,缺点是只验证端口能被访问,不关心端口背后的业务逻辑是否真的正常,比如MySQL端口3306还开着,但数据库连接数已满无法写入新数据,TCP探测依然会判定健康。
适用场景:对业务连续性要求不苛刻的内部系统,或者想用最低成本快速感知网络分区故障的场景,nginx上游服务器、LVS等传统负载均衡的默认健康检查方式,大多就是TCP探测。
HTTP/HTTPS请求探测:最贴近用户视角的检查
HTTP探测在TCP握手之上,多了构造请求、等待响应体、校验状态码的步骤,探测端发送GET请求到指定URL,收到200-399范围内的状态码就判定健康,收到4xx或5xx则判定异常,部分实现还支持校验响应体中的关键字,比如检查返回的JSON里status字段值是否为"ok"。
这种方式能直接反映用户请求路径的健康度,对Web服务、API网关、微服务接口的检查效果最为精准,Kubernetes的httpGet探针、简米云SLB的HTTP健康检查、AWS ALB的目标组检查,走的都是这条路径。
HTTPS探测:给HTTP路径加一层证书校验
HTTPS探测的实现路径和HTTP基本一致,区别在于探测端需要完成TLS握手,且可以配置是否校验服务端证书的有效期和信任链,对于线上对外服务的域名,多数团队会开启证书校验,这能顺带发现证书过期的问题,必须注意,开启证书校验的探测节点,需要提前把CA证书链同步到探测端所在服务器,否则会因信任问题导致误报。
ICMP Ping探测:网络层的存活信号
Ping走的是ICMP协议,用来检查目标主机的网络栈是否响应,它在网络设备层面的健康检查中用得比较多,但在应用层负载均衡中已经逐渐被淘汰,原因是Ping只能说明主机活着,主机活着但业务进程崩溃是常有的事,Ping出来的"健康"完全没有业务参考价值,另外很多云厂商的安全组默认禁Ping,导致误报率偏高。
负载均衡健康检查配置方法:从nginx到云厂商的实操路径
理解了协议层级,接下来看看现实中健康检查到底怎么配,不同平台的配置语法差异很大,但设计思路是相通的。
nginx主动健康检查配置逻辑
nginx社区版自带的health_check模块需要配合zone指令使用,配置在

upstream块内,以下是一个针对后端API服务的检查配置示例:
upstream backend_api {
zone backend 64k;
server 10.0.1.2:8080;
server 10.0.1.3:8080;
health_check interval=5s
fails=2
passes=1
uri=/api/health
match status_ok;
}
match status_ok {
status 200;
body ~ "ok";
}
这段配置的含义是:负载均衡每5秒向两个后端节点的/api/health接口发一次GET请求,连续失败2次标记节点不可用,恢复检查通过1次就重新放回流量池,并且要求响应状态码为200、响应体包含"ok"关键字。
nginx商业版和OpenResty还能做主动探测之外的健康度加权,比如根据探测响应时间动态调整转发权重,一般用在多级缓存节点间的流量调度上。
Kubernetes探针配置路径
K8s的探针有三种实现方式:exec命令、httpGet请求、tcpSocket连接,实际生产中最推荐用exec或httpGet组合使用,先探业务进程状态,再探接口响应。
以下为httpGet探针的典型配置:
livenessProbe:
httpGet:
path: /healthz
port: 8080
httpHeaders:
- name: X-Health-Check
value: kube-probe
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 2
failureThreshold: 3
这个配置里有个容易踩坑的细节:httpHeaders中自定义请求头很重要,很多业务框架会对非浏览器请求做拦截或限流,不加上这个请求头,探针请求可能被业务代码直接拒绝。
云负载均衡检查间隔的权衡
简米云、酷番云、AWS的负载均衡健康检查配置界面,核心参数都是检查间隔、超时时间、不健康阈值、健康阈值四项,行业共识认为,检查间隔设为5秒、超时3秒、不健康阈值3次、健康阈值2次,是覆盖故障发现速度和资源开销的平衡点,间隔低于3秒容易给后端造成无意义的请求压力,高于15秒则故障转移时间过长。
TCP和HTTP健康检查怎么选?核心对比与场景决策
TCP和HTTP的选型困惑,几乎每个做架构设计的人都会遇到,判断标准其实就一句话:你的用户是怎么访问服务的,探针就应该怎么探测,所有用户走HTTP协议访问,你偏用TCP探活,那就是自欺欺人。
| 对比维度 | TCP探测 | HTTP探测 |
|---|---|---|
| 探测链路 | 三次握手即可 | 完整请求响应链路 |
| 资源开销 | 极低 | 相对较高(涉及HTTP解析) |
| 故障感知精度 | 只能感知端口关闭/主机宕机 | 可感知应用内部异常、依赖故障 |
| 误判率 | 高(大量业务故障不改变端口状态) | 低(可校验状态码和响应体) |
| 配置复杂度 | 极简 | 需设计专门的健康检查接口 |
| 常见使用场景 | 数据库、Redis、消息队列 | Web服务、API网关、微服务 |
后端是数据库或中间件时,TCP探测优先
MySQL、Redis、Kafka这类基础组件,健康检查就应该用TCP方式,原因在于这些组件本身就提供了成熟的客户端驱动和连接池机制,应用层能感知到连接异常并自动重连,负载均衡只需判断端口存活,无需关心组件内部状态,强行给Redis做HTTP健康检查反而难以实施,因为Redis的标准协议是RESP而不是HTTP。
后端是Web应用或微服务时,HTTP探测必须安排上
对于Spring Boot、Go Gin、Node.js Express这类框架写的业务服务,TCP探活漏报率相当高,一个典型的场景是:后端代码里有个死循环线程池,占满了CPU,端口仍然正常响应TCP握手,但实际业务请求已经全部超时,只有HTTP健康检查配合自定义的/health接口,才能暴露这种问题。
这个/health接口的返回值设计有讲究,建议在接口里多做一步依赖状态的聚合检查,比如查询一次数据库、确认一次Redis连接池有可用连接,再返回200,但这步操作耗时不能超过1秒,否则健康检查本身会拖垮服务。
混合路径:先TCP后HTTP的两段式探测
部分严格要求可用性的架构,会采用两段式探测,第一段用TCP探测确认网络链路通,第二段用HTTP探测确认业务逻辑通,第一段失败时直接切换流量,第二段失败时仅摘除当前节点的写流量,保留读流量或直接全摘,这种模式在部署了服务网格的企业中逐渐普及,比如Istio就支持同时配置TCP和HTTP健康检查,作为前哨探针。
健康检查失败排查路径:从日志抓包到配置复查
当健康检查频繁报错时,不要一上来就怀疑后端服务挂了,按照以下排查路径走,能节省大量时间。
第一步:检查探针请求是否真的到达了后端
在业务服务器上执行tcpdump -nn -i eth0 port 8080,观察负载均衡节点的源IP是否定期出现在抓包结果中,如果没有抓包数据,跳过所有后端故障推测,直接排查负载均衡到后端的安全组、防火墙和子网路由,据统计,相当一部分健康检查报错,根源在于探针流量被安全策略挡在门外。
第二步:手动模拟探针请求验证返回值
用curl模拟一次探针请求,注意带和健康检查配置中相同的请求头。
curl -i -X GET https://service.example.com/api/health \ -H "Host: service.example.com" \ -H "X-Health-Check: kube-probe"
拿到返回值后,逐一核对状态码和响应体是否匹配配置要求,特别是当探针配置了body关键字校验时,响应体里多一个空格都会导致检查失败。
第三步:检查后端进程的并发连接数
健康检查本身会占连接资源,如果后端服务的最大连接数设置过小,或者连接泄漏严重,探针请求有可能被连接队列拒绝,造成检查失败的假象,此时查看后端日志会看到大量too many connections或connection refused记录。
第四步:确认健康检查是否受DNS解析时长拖累
少数负载均衡的探针目标不是IP而是域名,这类配置下,DNS解析超时同样会让健康检查失败,将探针目标直接改为后端的内网IP,或者优化DNS TTL,通常能解决问题。

健康检查配置里的三个常见认知误区
健康检查接口越复杂越好
健康检查接口的本质是快速反馈,不是全链路压测,如果接口内要聚合查十个下游系统的状态,任何一个抖动都会导致探针失败,进而引发大规模流量切换,建议健康检查接口只做基本的进程存活和本地依赖连接判断,不要做跨服务的远程调用。
健康检查失败阈值越大越稳
把不健康阈值从3次调到10次,确实能减少瞬时报障带来的误切换,代价是故障隔离时间被拉长,以一个5秒间隔的探针为例,10次阈值意味着最坏情况下50秒才摘除故障节点,这个时长的在线交易损失,远超健康检查带来的微妙稳定性收益。
健康检查只用于负载均衡
健康检查的价值远远不止流量调度,配合监控系统时,健康检查响应时间的变化趋势是发现服务性能劣化的早期信号,比如节点健康检查耗时从1ms涨到500ms,通常预示着该节点所在机器的磁盘IO或网络带宽正出现瓶颈,把健康检查的历史数据接入Prometheus或Grafana,能提前发现相当一部分潜在故障。
Q&A:健康检查探测方式常见问题
负载均衡健康检查配置方法里,TCP和HTTP能否同时生效?
可以,主流的开源负载均衡和云厂商产品都支持在同一组后端节点上配置多条健康检查策略,并且策略之间通常是"与"的关系,比如可以配置TCP探测校验端口存活,同时配置HTTP探测校验业务接口,两者均通过才标记为健康,具体到nginx,需要在upstream块内配置两个独立的health_check指令块,分别指定不同的match规则。
健康检查探测方式有哪些,哪个对性能影响最小?
从资源占用的角度看,TCP探测的影响最小,因为不需要构造HTTP报文,也不依赖后端应用接受和解析HTTP请求,直接在操作系统内核层面就能完成握手流程,这也解释了为什么数据库和消息队列中间件普遍采用TCP探活,而HTTP探测对性能影响的大小完全取决于健康检查路径的设计逻辑,一个设计良好的/health接口可以做到毫秒级响应且不产生额外的磁盘和网络IO,Kubernetes官方文档给出的建议是,探针的periodSeconds不要低于1秒,更高频率的探针不会带来可用性的提升,反而会干扰后端服务的正常请求处理。
nginx健康检查配置示例中,主动检查与被动检查有何不同?
主动检查由nginx的worker进程按照设定的间隔,主动向后端发起探针请求,结果即时更新,但会额外占用一定带宽和连接资源,被动检查则是nginx在转发真实业务请求时,发现连接失败或超时,才将节点标记为不可用,不额外消耗资源但发现故障的时机滞后,实际部署时建议以主动检查为主,被动检查作为兜底,nginx商业版中通过max_fails和fail_timeout参数即可开启被动检查能力。
