Skip to content

几十个服务互相调用,怎么不互相拖垮?—— 治理与稳定性 ​

属于 S4 Go 微服务 · 第三篇 上一篇:架构与gRPC 下一篇:面试题集

服务拆多了,治理问题接踵而至:服务怎么找到彼此?出了问题怎么发现?一个服务挂了怎么不拖垮别人?这一篇讲四件事:注册发现、可观测性、优雅上下线、熔断限流降级。

注册发现:服务怎么找到彼此 ​

服务实例是动态变化的(扩缩容、重启),调用方不能写死 IP。所以需要一个注册中心维护"服务名 → 实例列表"。流程是:实例启动时注册 + 心跳续期,调用方从注册中心拉列表,再负载均衡地选一个实例调用。

健康检查有两种:主动上报(定时心跳,超时剔除)和被动检查(调用失败上报)。实例下线要"先注销再停服务"。选型上,etcd 强一致(Raft)带租约,consul 带健康检查,ZooKeeper 老牌 CP 强一致——掌握原理和选型对比即可。

可观测性:出了问题怎么发现 ​

几十个服务,出问题靠"人肉看日志"是不现实的。可观测性有三大支柱:

  • 日志(Logging):离散事件,看"发生了什么"。
  • 指标(Metrics):聚合数值(QPS/延迟/错误率),看"整体趋势"。
  • 链路(Tracing):一次请求跨服务的路径和耗时,看"卡在哪一环"。

一句话:日志看单点,指标看全局,链路看路径。

优雅上下线:服务起停不能"硬来" ​

服务上线如果一启动就接流量,可能被瞬间打满(还没预热完);下线如果直接杀进程,正在处理的请求就丢了。

优雅下线的流程是:收到停止信号 → 停止接新请求 → 处理完在途请求 → 注销服务 → 退出。Go 里用 signal.NotifyContext + http.Server.Shutdown(ctx) 实现。优雅上线则是先完成依赖初始化、缓存预热,再注册接流量。

熔断、限流、降级:不拖垮系统的三件套 ​

下游服务挂了,如果调用方还一直傻等,就会级联雪崩——一个服务拖垮整个系统。三件套各自防一件事:

  • 限流:控制进入的请求量,超阈值拒绝(令牌桶/漏桶/滑动窗口)。
  • 熔断:下游连续失败超阈值,直接快速失败,不再调用。状态机是 Closed(正常)→ Open(熔断)→ Half-Open(探测)→ 恢复或重新熔断。
  • 降级:压力大或依赖故障时,关闭非核心功能,保核心。

还有一条铁律:所有 RPC 必须设超时(否则一个慢服务拖死所有调用方),而重试必须配合幂等(否则重复执行副作用)。


串起来 ​

微服务的治理是一套组合拳:注册发现解决"找到彼此",可观测性解决"发现问题",优雅上下线解决"起停不丢请求",熔断限流降级解决"不互相拖垮"。这些稳定性的基本功,比业务代码更能体现一个后端工程师的成熟度。

下一篇是 S4 的面试题集。

持续学习,持续构建。