一、故障的真实场景与初步排查
最近公司做年度促销的秒杀活动,当天下午三点,核心用户服务突然挂了一个节点,紧接着系统里的订单服务、商品服务开始批量报错,调用用户服务的接口全超时。运维同学第一时间排查监控,发现TSE注册中心的这个用户服务节点已经被标记为“下线”,剩下的两个节点也处于“不健康”状态,导致所有服务都找不到可用的用户服务实例,整个秒杀页面无法加载,影响了近千个用户的参与。后来翻了之前的配置,发现有两个之前没注意到的小坑,就是心跳和健康检查的设置,这次把这些坑拆解清楚,帮大家避免踩类似的雷。
1.1 为什么注册中心能管所有服务的死活?
用生活化的例子说,你平时点外卖时,平台会把所有商家列出来,这个商家列表就相当于微服务里的注册中心,每个入驻的商家(对应微服务的节点)要定期给平台发消息说“我还开门营业着”,这个消息就是心跳。如果商家超过一定时间没发消息,平台就会把它从列表里删掉,客人(其他服务)就找不到这个商家了,自然没法下单(调用接口)。
1.2 这次故障的具体排查过程
当时先看注册中心的节点状态,发现用户服务的三个节点里,一个已经崩了,剩下的两个节点的心跳都超时了,注册中心以为整个用户服务都挂了,所以把它从服务列表里清掉。再查配置,发现心跳间隔设的是10秒,超时时间是5秒——也就是说,节点刚发完心跳,注册中心过5秒就没收到下一个,就判定节点故障,相当于老板让员工每天打卡,员工10天打一次,老板5天没看到打卡就把员工开除了,这显然不合理。而且当时注册中心是单节点部署,整个注册中心挂了就全完了。
二、拆解心跳机制的常见配置陷阱
2.1 心跳的核心作用
简单说就是“报平安”,每个微服务节点会按固定时间间隔给注册中心发请求,告诉对方“我活着,能正常提供服务”,注册中心收到后会更新这个节点的状态。如果连续几次没收到,就会把这个节点标记为不可用,其他服务就不会再调用它了。
2.2 陷阱1:心跳间隔和超时时间设置不合理
刚才的故障里,间隔和超时设置得太紧凑,容易因为网络波动误判节点故障。那正确的配置应该是多少?根据不同场景调整,日常业务可以设间隔5秒,超时15秒——因为网络偶尔会有延迟,给节点留够缓冲时间,不会轻易踢下线。这里给出适配Spring Cloud Alibaba技术栈(与TSE注册中心兼容)的配置示例:
# 采用Spring Cloud Alibaba + Nacos作为微服务技术栈
spring:
cloud:
nacos:
discovery:
server-addr: 你的TSE注册中心地址:8848
# 心跳间隔:每5秒发送一次心跳,平衡实时性和网络消耗
heart-beat-interval: 5000
# 心跳超时时间:连续3次未收到心跳,判定节点故障(5秒×3=15秒)
heart-beat-timeout: 15000
# 健康检查类型选HTTP,比TCP更能确认服务内部正常
health-check-type: HTTP
# 健康检查路径:Spring Boot Actuator自动生成的健康接口,确保服务真的可用
health-check-path: /actuator/health
这个配置的核心是给网络波动留了缓冲空间,避免误判,之前的错误配置就是把超时设成了5秒,太严格了。
2.3 陷阱2:注册中心用单节点,不是集群
刚才的故障里,TSE注册中心是单节点,那个节点刚好出了点小问题,虽然只是暂时的,但导致整个注册中心的服务发现都失效了。就像外卖平台的服务器只有一台,服务器断网了,所有商家和顾客都没法用了。所以注册中心一定要用集群部署,TSE注册中心本身支持3节点或5节点集群,服务配置的时候要把所有节点的地址都写上,这样即使一个节点挂了,还有其他节点可用。示例配置如下:
// TSE注册中心集群配置,保证高可用
{
"spring": {
"cloud": {
"nacos": {
"discovery": {
"server-addr": "tse-node1:8848,tse-node2:8848,tse-node3:8848"
}
}
}
}
}
这里的配置把三个节点的地址都列出来,服务会自动选择可用的节点,不会因为单个节点故障导致注册中心不可用。
三、健康检查的配置坑点与规避方法
3.1 健康检查和心跳的区别
心跳只是检查节点有没有活着(进程在不在),但健康检查是检查服务内部是不是真的能正常提供功能——比如进程在,但核心业务线程挂了,心跳会正常发,但健康检查会返回失败。就像商家开着门,但厨房着火了,没法做饭,客人来了也没法下单,健康检查就是看厨房能不能正常做饭。
3.2 常见健康检查陷阱:路径写错
很多开发者会随便写健康路径,比如把路径写成/health,而Spring Boot Actuator的默认路径是/actuator/health,如果配置的时候写错,注册中心每次检查都会返回404或者500,就会判定节点不健康,即使节点是好的。之前就有个同事犯过这个错,把health-check-path写成/health,导致整个服务被下线,排查了半天才发现是路径写错了。
3.3 其他配置注意事项
比如健康检查的超时时间,不要设太小,比如设成1秒,服务处理健康接口需要时间,容易超时,设成3秒比较合适。另外,不要随便关闭健康检查,虽然会减少一点网络消耗,但会导致注册中心不知道服务内部的状态,容易出问题。
3.4 不同场景的配置选择
对于秒杀、支付这类高可用要求的场景,心跳间隔设3秒,超时设8秒,健康检查路径用Actuator的接口,检查类型选HTTP;对于邮件通知、日志采集这类低频服务,心跳间隔可以设15秒,超时设45秒,减少不必要的网络请求。
四、总结
这次故障给我们的教训是,微服务的注册中心配置里,心跳和健康检查的细节非常重要,不能用默认值就不管了。尤其是用TSE这类兼容Nacos的注册中心时,要根据业务场景调整心跳和健康检查的参数,必须用注册中心集群,不能单节点。平时要多监控注册中心的心跳成功率和健康检查的状态,发现超时要及时排查,不要等线上出问题才补救。很多线上的大故障都是因为这些小配置的坑没注意到,只要把这些细节做好,就能避免很多服务发现失败的问题。
Comments