Yujun's Blog

Microservice(四):服务降级和熔断

June 6, 2025 (5mo ago)SD

服务降级与服务熔断

今天继续来说说关于系统保护的话题,

在构建高可用的分布式系统中,通常会使用这两种互补的机制来确保系统的稳定性和可用性。

在构建高可用、高并发的分布式系统中,“稳定性”是压倒一切的追求。当双十一的零点钟声敲响,亿万流量如洪水般涌入时,为什么像淘宝、京东这样的巨型应用依然能让您完成核心的下单支付,即便某些次要功能(如商品推荐、用户评论)暂时无法加载? 这背后,就是我们今天要深入探讨的两个核心概念:服务降级(Degradation)服务熔断(Circuit Breaking)

虽然它们都服务于系统的高可用目标,防止故障蔓延和系统雪崩。但其触发时机、解决的问题和实现方式却截然不同。 即可以从三方面去区分它们的不同。

一、服务降级 (Degradation / Graceful Degradation)

服务降级是指当系统面临高并发、资源紧张或部分服务不可用时,为了保证核心功能的正常运行,牺牲部分非核心功能或提供简化服务的一种策略。它是一种“有损”但“可用”的妥协。

服务降级是从系统的资源角度来考虑的,由于系统资源是有限的,在核心业务流量超过预估峰值的情况下,可能会因为系统资源不足,导致无法提供核心服务。因此我们可以对非核心业务进行限流或者降级甚至是下线。来让出非核心服务所占有的系统资源,提供给核心服务使用,从而保证我们系统核心服务的正常运行。

触发条件:

  • 系统整体负载过高: 服务器 CPU、内存、网络等资源利用率过高。
  • 特定服务出现问题: 某个非核心服务或依赖服务出现故障。
  • 业务高峰期: 预知会有大量流量涌入(可以手动触发降级)。
  • 非核心功能异常: 某个辅助功能无法正常提供服务。

降级的目的是应对系统自身的资源不足问题(如 CPU、内存、网络带宽占满),它是一种内部的主动防御

例子: 双十一秒杀时,电商网站为了保证用户能成功下单支付(核心功能),可能会暂时关闭“猜你喜欢”的商品推荐功能,或者用户评论区显示“服务繁忙,请稍后再看”。

想象一下,你正在指挥一艘在大海中航行的货轮,突然遭遇了特大风暴。为了保证船体和核心货物(以及船员)的安全,你下令将甲板上那些不那么重要的集装箱抛入大海,以减轻负载,确保货轮能撑过风暴。

服务降级(Service Degradation) 就是这种“丢车保帅”的策略。

核心定义:当系统整体负载超出其承载能力时,主动或被动地关闭或简化部分非核心功能,将有限的系统资源释放出来,以保障核心业务的稳定运行。

应对方式:

  • 关闭非核心功能: 例如,电商网站在高压下关闭商品推荐、用户评价、历史订单查询等非核心功能,只保留核心的商品浏览和购买。
  • 返回默认值/缓存数据: 当无法获取实时数据时,返回一个预设的默认值、占位符数据,或者使用旧的缓存数据。
  • 简化服务逻辑: 例如,图片上传从高清压缩为标清,搜索结果从精确匹配改为模糊匹配。
  • 延迟处理: 将某些同步任务改为异步处理,或者将请求放入消息队列,稍后处理。
  • 限制并发量: 限流,对某些接口设置访问上限。

降级的常见方式

根据业务场景,降级策略可以非常灵活,以下是一些常见的实现方式:

  1. 功能降级/页面降级
  • 片段降级:在电商商品详情页,当系统压力巨大时,可以暂时关闭“商品推荐”、“买家秀”等区块,只保留商品主图、价格、库存和购买按钮。用户依然可以完成购买,核心链路不受影响。
  • 页面跳转:当整个服务(如营销活动页)压力过大时,可以直接将用户导向一个静态的、预先准备好的“活动火爆,请稍后再试”的页面,避免大量请求拖垮后端服务。
  1. 读/写服务降级
  • 写降级:在秒杀场景下,库存扣减是热点操作。可以将请求先写入高速的缓存(如 Redis)或消息队列(如 Kafka),然后通过异步任务缓慢同步到数据库。这极大地降低了数据库的瞬时压力,保证了最终一致性。此时,DB 被降级为 Cache。
  • 读降级:当数据库或底层服务出现问题时,可以降级为只从缓存中读取数据。即使数据可能不是最新的(存在一定延迟),但至少保证了前端页面的可用性,避免了大量报错。
  1. 延迟服务:对于一些非实时性的操作,比如用户发表评论后增加积分,可以将“增加积分”这个操作放入消息队列中,等系统负载恢复正常后再慢慢消费处理,而不是实时执行。

降级的分类

  • 人工降级:通过后台开关手动执行。通常用于可预知的大流量场景,如双十一大促、秒杀活动前,运维或开发人员会提前手动开启降级策略。
  • 自动降级:系统根据预设的指标(如系统负载、CPU使用率、服务响应时间、失败次数)自动触发。例如,当系统平均响应时间超过 500ms 时,自动关闭某个非核心功能。

二、服务熔断 (Circuit Breaker)

是对服务调用方的保护。防止它被其他服务拖垮。

服务熔断就像家里的​电路断路器​。当家里的电器短路或电流过载时,断路器会自动跳闸,切断电源,而不是让电线烧毁甚至引发火灾。

服务直接必定会有相关的依赖关系。你的服务 A 依赖于服务 B(比如订单服务依赖于库存服务)。某天,服务 B 因为自身故障,响应变得极度缓慢甚至无响应。此时,所有调用服务 B 的请求都在服务 A 内部堆积,占用了大量的线程和连接资源,最终导致服务 A 也被拖垮,无法响应任何其他请求。接着,依赖服务 A 的服务 C、D…也相继崩溃。这就是可怕的雪崩效应(Cascading Failure)。

服务熔断(Service Circuit Breaking) 就是为了斩断这种连锁反应的保护机制。

核心定义:当某个下游依赖服务持续出现故障(如超时、大量错误)时,为了保护调用方(上游服务)的资源,暂时切断对该故障服务的调用,并快速返回一个错误或备用响应(Fallback)。

熔断的目的是应对外部依赖的故障问题,它是一种对外的被动保护。它的灵感来源于现实世界中的“保险丝”,当电流过大时,保险丝会熔断以保护整个电路和电器。

熔断器的三态模型

一个成熟的熔断器通常包含三个状态,这是理解其工作原理的关键:

  1. Closed(闭合状态)
  • 这是正常状态,所有请求都能正常通过熔断器到达下游服务。
  • 熔断器会持续监控调用失败的次数或比率。当失败率达到预设的阈值时,熔断器状态切换为“Open”。
  1. Open(断开状态)
  • 在此状态下,所有对下游服务的请求都会被立即拦截,不再发送到下游,而是直接返回一个预设的错误或执行降级逻辑(Fallback)。这实现了“快速失败”,避免了资源被无谓等待消耗。
  • 开启一个计时器(例如,等待 30 秒)。当计时器结束后,熔断器进入“Half-Open”状态。
  1. Half-Open(半开状态)
  • 这是一个试探状态。熔断器会允许一小部分“探测”请求通过,去调用下游服务。
  • 如果这些请求成功:说明下游服务可能已经恢复。熔断器会关闭,回到“Closed”状态,恢复正常调用链路。
  • 如果这些请求仍然失败:说明下游服务还未恢复。熔断器会重新回到“Open”状态,并重置计时器,继续等待下一轮探测。

三、核心区别:一张图看懂降级与熔断

虽然两者都为了高可用,但它们的关注点和作用域完全不同。

特性服务降级 (Degradation)服务熔断 (Circuit Breaking)
目标应对自身的负载压力,保证核心功能可用应对外部依赖的故障,防止自身被拖垮
触发原因系统负载、CPU/内存使用率、QPS过高依赖服务超时、错误率过高、网络故障
管理视角业务视角,从整体功能考虑,有核心、非核心之分技术视角,从服务依赖关系考虑,保护调用方
实现方式主动或被动关闭/简化部分功能(功能开关、读写分离、静态化)拦截对故障服务的调用,快速失败(状态机模型)
关系相互关联。熔断是降级的一种表现形式。例如,因为B服务被熔断了,A服务可以降级处理,不显示B服务提供的数据。

简单来说:降级是“对内”的,为了应对自己的“体力不支”;熔断是“对外”的,为了应对朋友的“不靠谱”。


五、舱壁模式(Bulkhead Pattern)

想象一艘大船,为了防止船体某处破损导致整艘船沉没,船的内部被分割成了多个独立的水密隔舱(Bulkheads)。即使一个隔舱进水,其他隔舱依然能保持完好,船只仍有很大机会保持漂浮。

舱壁模式的核心思想就是:将系统资源或组件划分成独立的、隔离的单元(池),以防止一个单元的故障或资源耗尽影响到其他单元,从而提高系统的整体韧性和可用性。

在软件系统中,这些“资源”可以是:

  • 连接池(数据库连接、HTTP连接)
  • 线程池
  • 内存区域
  • 进程

如果系统中的某个部分(比如一个对外部服务的调用)出现问题(例如响应缓慢或失败),这个故障应该被限制在该部分所分配的“隔舱”内,而不应该蔓延并耗尽整个系统的资源,导致整个应用程序崩溃。

四、主流实现方案:Hystrix、Sentinel 与 Resilience4J

在 Spring Cloud 生态中,有多个成熟的库可以帮助我们实现熔断和降级。

  1. Netflix Hystrix
  • 地位:元老级熔断器组件,功能强大,经过了 Netflix 的大规模生产验证。
  • 特点:主要通过线程池隔离来实现资源保护,虽然隔离性强,但也带来了额外的线程切换开销。
  • 现状:目前已进入维护模式,Netflix 官方不再开发新功能。
  1. Alibaba Sentinel
  • 地位:后起之秀,目前是 Spring Cloud Alibaba 的核心组件,功能极其丰富。
  • 特点
    • 轻量级隔离:默认使用信号量隔离,开销更小。
    • 功能全面:除了熔断降级,还集成了流量控制(限流)、流量整形(匀速/预热排队)、系统自适应保护等强大功能。
    • 控制台强大:提供开箱即用的控制台,可以实时监控、动态修改规则,非常强大。
  • 推荐:目前是新项目的首选。
  1. Resilience4J
  • 地位:一个轻量级、模块化的容错库,设计思想受 Hystrix 启发但无外部依赖。
  • 特点:函数式编程风格,易于与其他函数库(如 Vavr)组合。提供了熔断、限流、重试、舱壁隔离等独立的模块,可以按需引入。

对比 SentinelHystrix,Sentinel 在性能、功能的丰富度以及控制台的易用性上都更具优势,特别是在系统自适应保护方面,它可以根据入口 QPS、系统 Load Average 等指标来动态调整流量,是其一大亮点。

面试题:熔断和降级有什么区别?

面试题:Sentinel 有哪些熔断降级策略?

总结

服务降级和服务熔断是微服务架构下保障系统稳定性的两大基石,缺一不可。

  • 服务降级是一种全局性的容错策略,它从业务层面出发,通过牺牲次要体验来换取核心业务的稳定,体现了“有损服务”的设计思想。
  • 服务熔断是一种局部性的链路保护机制,它从技术依赖层面出发,通过“熔断-恢复”的自动化机制来防止故障蔓延,是构建“弹性”系统的关键。

在复杂的分布式世界里,故障是常态。理解并熟练运用降级与熔断,将使你的系统在面对未知风暴时,依然能够优雅地运行,而不是不堪一击、瞬间崩溃。

Comments