
面试官:什么是服务雪崩,该如何避免?说说看你对熔断、限流和降级的理解(关联和区别)
题目概览:
-
说说看什么是服务雪崩,该如何避免?
-
能具体说说看什么是服务熔断?它的作用是什么?熔断机制是如何工作的?
-
能说说看Hystrix是如何实现熔断的?它的熔断流程是怎样的?
-
服务降级有哪些常见的策略?请列举并解释。
-
你能否分享一个在实际项目中应用服务降级的案例?
面试官:说说看什么是服务雪崩,该如何避免?
服务雪崩效应是一种在微服务架构中常见的现象,它指的是因“服务提供者的不可用”导致“服务调用者不可用”,并将不可用逐渐放大的情况。具体来说,当某个服务提供者因为压力过大、网络故障、硬件故障等原因而无法正常提供服务时,依赖于该服务的调用者就会因为无法成功调用其接口而造成线程阻塞或资源耗尽,进而也无法正常提供服务。随着这种情况的蔓延,越来越多的服务会因为依赖关系的存在而受到影响,最终导致整个微服务架构的崩溃。

服务雪崩效应的形成过程通常可以分为以下几个阶段:
-
服务提供者不可用 :由于各种原因(如过载、故障等),某个服务提供者无法正常提供服务。
-
服务调用者受阻 :依赖于该服务提供者的服务调用者因为无法成功调用接口而受阻,造成线程阻塞或资源耗尽。
-
连锁反应 :受阻的服务调用者可能也是其他服务的提供者,因此它们无法提供服务会导致更多的服务调用者受阻,形成连锁反应。
-
系统崩溃 :随着连锁反应的持续,越来越多的服务受到影响,最终导致整个微服务架构的崩溃。
为了避免服务雪崩效应的发生,可以采取以下措施:

-
服务降级与熔断 :在服务调用者中添加降级逻辑,当检测到服务提供者不可用时,自动切换到降级方案,避免因为等待服务提供者响应而造成资源耗尽。同时,可以使用熔断器来自动隔离故障服务,防止其影响整个系统。
-
限流与超时控制 :对服务调用进行限流控制,避免因为请求量过大而导致服务过载。同时,设置合理的超时时间,避免因为等待服务响应时间过长而导致资源浪费。
-
资源隔离 :使用进程隔离、线程隔离等技术手段,将不同服务之间的资源隔离开来,防止因为某个服务的故障而影响其他服务。
-
监控与预警 :建立完善的监控体系,实时监测服务的运行状态和性能指标。当检测到异常时,及时发出预警并采取相应措施进行处理。
面试官:请谈谈你对熔断、降级和限流的理解。
以下是我对熔断、降级和限流的理解:
熔断(Circuit Breaker)
定义 :
熔断机制是一种用于处理分布式系统中服务间调用的自我保护策略。它类似于电路中的保险丝,当电流过大时,保险丝会熔断以保护电路不受损坏。在微服务架构中,熔断器用于监控服务的调用情况,并在服务出现故障时自动触发熔断,以防止故障扩散。
工作原理 :
熔断器通常有三种状态:关闭、打开和半开。在关闭状态下,服务调用正常进行。当服务调用失败率达到设定的阈值时,熔断器会切换到打开状态,拒绝所有对该服务的调用。在一段时间后,熔断器会进入半开状态,允许部分请求通过以测试服务是否恢复。如果请求成功,则熔断器会切换回关闭状态;如果请求失败,则熔断器会重新切换到打开状态。
降级(Fallback)
定义 :
降级是指在系统出现故障或压力过大时,为了保证系统的整体可用性,暂时降低某些非核心功能或服务的性能或可用性。降级通常是在熔断机制触发后执行的一种自我保护策略。
工作原理 :
降级策略可以根据业务需求进行定制,如返回默认值、使用缓存数据、提供简化版本的服务等。当熔断器打开时,系统会执行降级逻辑,以减轻故障服务对系统的影响。
应用场景 :
降级通常用于那些对系统稳定性不是至关重要的服务,如推荐系统、广告系统等。在这些服务出现故障时,可以通过降级策略来保证系统的整体可用性,同时减少对用户的影响。
限流(Rate Limiting)
定义 :
限流是指对系统或服务的请求进行流量控制,以防止系统因过载而崩溃。限流机制通过限制请求的数量或速率来保护系统资源,确保系统能够稳定地提供服务。
工作原理 :
限流机制通常使用令牌桶算法、漏桶算法或滑动窗口算法等算法来实现。这些算法会根据设定的请求速率和容量来控制请求的通过情况。当请求数量超过设定的阈值时,系统会拒绝部分请求或进行排队处理。
应用场景 :
限流机制通常用于那些容易受到流量冲击的服务,如API接口、登录服务等。通过限制请求的速率和数量,可以保护系统资源不被过度消耗,确保系统能够稳定地提供服务。
其中,熔断和降级容易混淆,需要注意的是熔断和降级的区分:
熔断和降级都是微服务架构中常用的自我保护策略,它们之间存在紧密的关联,但也有一些显著的区别。以下是对熔断和降级的关联与区别的详细阐述:
关联
- 目的相同 :
* 熔断和降级都是为了保护系统的稳定性和可用性,防止因某个服务的故障而导致整个系统的崩溃。
- 触发条件相关 :
* 在某些情况下,熔断机制触发后会自动执行降级逻辑。例如,当某个服务的调用失败率达到设定的阈值时,熔断器会打开,此时系统会执行降级逻辑,以减轻故障服务对系统的影响。
- 协同工作 :
* 熔断和降级通常协同工作,共同构成微服务架构中的自我保护机制。通过熔断机制快速切断故障点,然后通过降级策略保证系统的整体可用性。
区别
- 概念不同 :
* 熔断(Circuit Breaker)是一种自动停盘机制,当服务调用失败率达到设定的阈值时,熔断器会打开,拒绝所有对该服务的调用,以防止故障扩散。
* 降级(Degradation)则是指在系统出现故障或压力过大时,为了保证系统的整体可用性,暂时降低某些非核心功能或服务的性能或可用性。
- 触发条件不同 :
* 熔断的触发条件通常是服务调用失败率达到设定的阈值。
* 降级的触发条件则更加灵活,可以根据业务需求进行定制,如系统压力过大、资源不足、依赖服务不可用等。
- 执行逻辑不同 :
* 熔断机制在触发后会直接拒绝所有对该服务的调用,直到熔断器恢复到关闭状态。
* 降级策略则更加灵活,可以根据业务需求提供不同的降级方案,如返回默认值、使用缓存数据、提供简化版本的服务等。
总体而言,降级是一种退而求其次的选择,而熔断却是整体不可用。
面试官:能具体说说看什么是服务熔断?它的作用是什么 ** ** ?熔断机制是如何工作的?
服务熔断是分布式系统架构中的一个重要概念,用于提高系统的韧性和可靠性。以下是对服务熔断及其作用的详细解释:
服务熔断的定义
服务熔断是一种控制服务访问速率的机制,它能够在某个服务出现故障、延迟过高或者达到预设的阈值时,暂时中断该服务的调用链路。
服务熔断的作用
- 防止雪崩效应 :
* 在分布式系统中,一个服务的故障可能会引发连锁反应,导致多个关联服务都出现问题,进而引发整个系统的崩溃。服务熔断机制通过快速地关闭有问题的服务接口,可以有效防止这种雪崩效应的发生。
- 保护关键服务 :
* 在分布式系统中,一些关键服务对于整个系统的正常运行至关重要。通过配置熔断策略,可以优先保护这些关键服务,确保它们在面临高负载或故障时仍然能够正常运行。
- 优化资源利用 :
* 在服务熔断机制的作用下,系统可以更加合理地分配和利用资源。当某个服务出现故障时,系统可以迅速将资源分配给其他正常运行的服务,从而提高资源的利用率和系统的整体性能。
下面是熔断机制的工作原理的详细解释:
熔断器的状态
熔断器通常有三种状态:关闭(Closed)、打开(Open)和半开(Half-Open)。
-
关闭状态 :在正常情况下,熔断器处于关闭状态,允许服务调用正常进行。
-
打开状态 :当服务调用的失败次数或错误率达到设定的阈值时,熔断器会切换到打开状态。此时,所有对该服务的调用都会被直接拒绝,并返回预设的错误响应,以防止故障服务的进一步扩散。
-
半开状态 :在熔断器打开一段时间后(通常是一个预设的休眠时间窗口),熔断器会进入半开状态。在这个状态下,它会允许部分请求通过,以测试服务是否已经恢复正常。如果请求成功,则熔断器会切换回关闭状态;如果请求失败,则熔断器会重新切换到打开状态。
熔断机制的工作流程
-
服务调用监控 :熔断机制会监控每个服务的调用情况,包括请求数量、成功数量、失败数量等。这些数据被用于评估服务的健康状况。
-
熔断条件判断 :当在一定时间窗口内(如统计时间窗),失败请求的数量达到预设的阈值(如错误百分比阈值),且请求总数超过请求总数阈值时,熔断机制会触发熔断。
-
熔断器状态切换 :
* 当触发熔断条件时,熔断器会从关闭状态切换到打开状态,拒绝所有对该服务的调用。
* 在熔断器打开一段时间后,会自动进入半开状态,允许部分请求通过以测试服务是否恢复。
* 根据测试请求的结果,熔断器会决定是切换回关闭状态还是重新切换到打开状态。
- 服务降级与恢复 :在熔断器打开状态下,通常会执行服务降级逻辑,如返回默认值或缓存数据,以保证系统的基本可用性。当服务恢复正常后,熔断器会切换回关闭状态,服务调用将恢复正常。

熔断机制的实现方式
在微服务架构中,熔断机制可以通过多种框架实现,如Netflix的Hystrix、Resilience4j等。这些框架提供了丰富的配置选项和注解支持,使得在微服务中实现熔断机制变得简单而高效。
以Hystrix为例,它通过在服务调用方法上添加@HystrixCommand注解,并指定fallback方法来实现熔断机制。当服务调用失败时,Hystrix会自动调用fallback方法作为备选方案。同时,Hystrix还提供了丰富的配置选项,如错误率阈值、请求总数阈值、熔断时间窗口等,以满足不同场景下的需求。
面试官:你刚刚有提到 Hystrix,能说说看 Hystrix 是如何实现熔断的?它的熔断流程是怎样的?
Hystrix是一个用于处理分布式系统的延迟和容错的开源库,它实现了断路器模式(Circuit Breaker
Pattern)。以下是Hystrix实现熔断的具体方式和熔断流程的详细解释:
Hystrix实现熔断的方式
- 线程池隔离 :
* Hystrix通过将每个依赖服务的调用放入独立的线程池中执行,实现对依赖服务的隔离。
* 当某个依赖服务出现延迟或故障时,只会影响当前线程池的执行,而不会波及其他服务或整个系统的稳定性。
- 超时控制 :
* Hystrix为每个依赖服务设置一个超时时间。
* 如果依赖服务的执行时间超过设定的超时时间,Hystrix会快速失败,防止长时间等待导致资源浪费。
- 熔断器 :
* Hystrix的熔断器监控依赖服务的调用情况。
* 当调用失败次数达到设定阈值时,熔断器会打开,暂时阻止对该依赖服务的调用,避免连锁故障。
* 在熔断器打开状态下,Hystrix会执行降级逻辑,返回默认值或缓存数据,以保证系统的正常运行。
Hystrix的熔断流程
- 服务调用监控 :
* Hystrix监控每个依赖服务的调用情况,包括请求数量、成功数量、失败数量等。
* 这些数据被用于评估依赖服务的健康状况。
- 熔断条件判断 :
* 当在一定时间窗口内(如统计时间窗),失败请求的数量达到预设的阈值(如错误百分比阈值),且请求总数超过请求总数阀值时,Hystrix会触发熔断。
* 默认的失败比例阈值是50%,请求次数最少不低于20次。
- 熔断器打开 :
* 一旦触发熔断,熔断器会立即打开。
* 在熔断器打开状态下,所有对该依赖服务的请求都会被拒绝,并直接返回降级结果或执行降级逻辑。
* 熔断器打开后会启动一个休眠时间窗(如默认5秒),在此期间内,熔断器保持打开状态。
- 休眠时间窗与半开状态 :
* 休眠时间窗到期后,熔断器会进入半开状态。
* 在半开状态下,Hystrix允许部分请求通过,以检查依赖服务是否已经恢复。
* 如果这些请求成功,则认为服务已恢复正常,熔断器会关闭;如果仍有请求失败,则熔断器会重新打开,并重新计时休眠时间窗。
- 熔断器关闭 :
* 当依赖服务恢复正常,且在一定时间窗口内没有再次触发熔断条件时,熔断器会关闭。
* 在熔断器关闭状态下,所有请求都会正常调用依赖服务。
面试官:熔断器如何 支持自定义降级逻辑,怎么实现?
实现自定义降级逻辑的方式因熔断器框架的不同而有所差异,但通常可以通过以下几种方式来实现:
一、基于注解的自定义降级逻辑
在一些熔断器框架中(如Hystrix),可以通过在需要熔断的方法上添加特定的注解(如@HystrixCommand),并指定一个fallback方法来实现自定义降级逻辑。当熔断器触发时,框架会自动调用这个fallback方法。
例如,在Hystrix中,你可以这样定义自定义降级逻辑:
@HystrixCommand(fallbackMethod = "customFallback")public String someServiceMethod() { // 正常服务逻辑}
public String customFallback() { // 自定义降级逻辑,如返回默认值或错误信息 return "Service is down, please try again later.";}
`
二、基于AOP的自定义降级逻辑
通过定义一个切面类,并在其中编写降级逻辑的代码,然后将这个切面类应用到需要熔断的服务方法上。当熔断器触发时,AOP框架会自动调用切面类中的降级逻辑。
以下是一个简单的示例,展示了如何使用Spring AOP来实现基于AOP的自定义降级。
首先,确保你的项目中包含了Spring AOP的依赖。如果你使用的是Maven,可以在 pom.xml 中添加以下依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId></dependency>
定义一个切面类,该类包含降级逻辑:
import org.aspectj.lang.annotation.AfterThrowing;import org.aspectj.lang.annotation.Aspect;import org.springframework.stereotype.Component;
@Aspect@Componentpublic class DegradationAspect {
// 定义降级逻辑的方法 public String degrade() { // 这里可以返回默认值、错误信息或执行其他降级操作 return "Service is degraded. Please try again later."; }
// 定义一个切点,该切点会匹配所有带有@Degrade注解的方法 @AfterThrowing(pointcut = "@annotation(degrade)", throwing = "ex") public void handleDegrade(Exception ex, Degrade degrade) { // 这里可以记录日志、发送告警等 // 然后执行降级逻辑,这里通过抛出运行时异常来模拟返回降级结果 // 注意:在实际应用中,你可能需要更优雅的方式来处理降级逻辑,比如使用自定义异常或返回类型 throw new RuntimeException(degrade.value() + " - " + ex.getMessage()); // 或者,如果你不想抛出异常,而是想直接返回降级结果,你可能需要修改方法签名和调用方式 // 例如,使用ThreadLocal或其他机制来传递降级结果 }}
定义一个注解,用于标记需要降级的方法:
import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;
@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interface Degrade { String value() default "Service is degraded";}
将这个注解应用到需要降级的服务方法上:
import org.springframework.stereotype.Service;
@Servicepublic class SomeService {
@Degrade("Payment service is temporarily unavailable") public String pay(String userId, double amount) { // 这里是支付服务的正常逻辑 // 如果支付服务失败,将触发DegradeAspect中的handleDegrade方法 // 为了模拟失败,这里直接抛出一个异常 throw new RuntimeException("Payment failed"); }}
在调用 SomeService#pay 方法时,如果发生异常, DegradeAspect#handleDegrade
方法将被触发,并执行降级逻辑。在这个示例中,降级逻辑是通过抛出一个运行时异常来实现的,异常信息中包含了降级提示和原始异常信息。
面试官:服务降级有哪些常见的策略?请列举并解释。
服务降级是在面对系统负载过高、资源不足或外部依赖故障等异常情况下,通过临时屏蔽某些功能或改变服务行为,以保证核心功能的可用性和性能稳定性的一种策略。以下是一些常见的服务降级策略及其解释:
一、功能降级
-
定义 :暂时关闭一些非核心的服务功能,以确保核心服务的稳定运行。
-
示例 :
-
搜索引擎可以关闭相关搜索结果或广告推荐等非核心功能。
-
电商网站可以关闭推荐商品、评论等非关键功能。
-
二、请求降级
-
定义 :对某些请求进行限流或拒绝,特别是那些计算密集或者对系统影响较大的请求。
-
示例 :
-
在高并发场景下,对部分用户的请求进行限流,以减少服务器的负载。
-
对计算密集型请求进行降级处理,如将复杂的计算任务延迟执行或返回近似结果。
-
三、数据降级
-
定义 :简化数据处理流程,如提供缓存数据而非实时数据,以降低对数据库的查询压力。
-
示例 :
-
在数据库查询性能下降时,使用缓存数据代替实时数据,以提高响应速度。
-
在数据更新频率较低的场景下,使用静态数据代替实时数据,以减少对数据库的访问次数。
-
四、用户降级
-
定义 :根据用户级别或请求来源,优先保障VIP用户或内部用户的请求,对于普通用户的请求则可能进行限流或拒绝。
-
示例 :
-
在系统负载较高时,优先处理VIP用户的请求,确保他们的服务体验。
-
对内部用户的请求进行优先处理,以确保业务运营的正常进行。
-
五、前端降级
-
定义 :通过控制用户界面上的展示和交互来减少对后端服务的请求。
-
示例 :
-
在高负载时暂时去除某些耗时的图表或功能按钮,只展示核心内容。
-
通过静态化页面或简化页面布局来减少对后端服务的请求量。
-
六、业务逻辑降级
-
定义 :在业务逻辑中根据当前系统状态或用户需求进行判断,决定是否执行某些非关键的功能或采取替代性方案。
-
示例 :
-
在库存紧张时,限制用户的购买数量或提供替代商品。
-
在搜索功能出现故障时,提供基于缓存的搜索结果或推荐用户使用其他搜索方式。
-
七、数据访问降级
-
定义 :在数据库或其他外部依赖出现故障或性能问题时,使用缓存、降低查询精确度或返回默认值等方式进行数据访问降级。
-
示例 :
-
在数据库连接池资源紧张时,使用缓存数据代替实时数据库查询。
-
在查询结果不准确时,返回默认值或近似值以避免系统崩溃。
-
八、多级降级
-
定义 :根据系统负载和故障情况,逐步降低服务级别,以确保核心服务的稳定运行。
-
示例 :
-
在系统负载逐渐升高时,先关闭部分非核心功能,再逐步降低服务质量(如响应时间、并发量等)。
-
在严重故障情况下,直接切换到备用系统或提供有限的服务。
-
九、开关降级
-
定义 :通过配置开关来控制服务的降级行为,以便在需要时快速切换服务状态。
-
示例 :
-
在大促活动前,通过配置开关关闭部分非关键功能,以确保核心交易流程的流畅进行。
-
在系统维护期间,通过配置开关将服务切换到维护模式,以减少对用户的干扰。
-
面试官:你能否分享一个在实际项目中应用服务降级的案例?
当然可以。下面是一个在实际项目中应用服务降级的案例:
案例背景
在一个电商系统中,用户可以通过发表评论来分享对商品的看法。评论功能中包括一个敏感词过滤服务,用于在用户发表评论时检测并过滤掉敏感词。这个服务依赖于一个第三方API,但在某些情况下,该API可能会因为各种原因变得不可用。
问题与挑战
-
第三方API不可用 :当敏感词过滤服务的第三方API不可用时,整个评论功能可能会受到影响,导致用户无法发表评论。
-
系统稳定性 :为了保障系统的整体稳定性,不能因为一个非核心服务的故障而导致整个评论功能瘫痪。
-
用户体验 :需要确保用户在评论功能中的体验不受影响,即使敏感词过滤服务暂时不可用。
解决方案
- 服务降级策略 :
* 当敏感词过滤服务的第三方API不可用时,启动服务降级策略。
* 在服务降级期间,不再调用第三方API进行敏感词过滤。
* 改为在程序中硬编码一个默认的评论内容,或者允许评论直接通过(但标记为未过滤)。
- 实施步骤 :
* 在代码中添加敏感词过滤服务的降级逻辑。
* 配置监控系统,当检测到敏感词过滤服务的第三方API不可用时,自动触发降级逻辑。
* 在降级期间,记录降级原因和降级影响,以便后续分析和处理。
- 测试与验证 :
* 在测试环境中模拟第三方API不可用的情况,验证降级逻辑是否正确触发。
* 确保在降级期间,用户仍然可以发表评论,并且评论能够正确保存到数据库中。
* 监控系统在降级期间的表现,确保系统稳定性不受影响。
效果与收益
-
系统稳定性提升 :通过服务降级策略,成功避免了因第三方API不可用而导致的评论功能瘫痪问题。
-
用户体验优化 :即使在敏感词过滤服务不可用的情况下,用户仍然能够顺利发表评论。
欢迎在评论区留言表达看法和问题,阿沛会一一作出回复。
如果本文对大家有帮助,麻烦大家动动小手点个免费的“赞”或“在看”,大家的鼓励就是阿沛持续更新的动力~

– 往期精彩 –
Redis面试题:什么是Redis的大key和热key,它们会造成什么问题,如何解决?
面试官:服务器如何处理数万并发客户端连接(C10K问题)?Reactor模型和Proactor模型如何实现高并发?什么是惊群效应
华为一面:说说看MySQL的索引类型及其作用?什么是聚簇索引和非聚簇索引?索引失效的情况有哪些?说说看回表、覆盖索引和索引下推?