源码分析 Sentinel DegradeSlot 熔断实现原理

1、DegradeSlot 概述

Sentinel 中的熔断实现类为 DegradeSlot。DegradeSlot 的类定义如下图所示:
在这里插入图片描述
由此可见,熔断主要实现逻辑定义在 DegradeRuleManager 的 checkDegrade 方法中。
DegradeRuleManager#checkDegrade
在这里插入图片描述代码@1:首先从 degradeRules 熔断规则缓存中获取资源的熔断规则。

代码@2:遍历熔断规则列表。

代码@3:调用熔断规则 DegradeRule 的 passCheck,如果该方法返回 false,则表示需要熔断,则抛出 DegradeException 异常。

即实现熔断的核心逻辑在 DegradeRule 中。

2、DegradeRule 详解

在介绍 DegradeRule 之前我们先来看看 sentinel-dashboard 关于熔断降级规则的配置:
在这里插入图片描述
我们可以直观的得知,降级规则可以根据如下三个指标进行设置:RT(响应时间)、异常比例、异常数。

2.1 DegradeRule 类图

在这里插入图片描述

  • double count
    上面配置规则中对应的配置值,例如当降级策略为RT时,表示设置的响应时间值,其他类似。
  • int timeWindow
    降级发生后多久进行恢复,即结束降级,单位为毫秒。
  • int grade
    降级策略,可以选值如下:
    1)DEGRADE_GRADE_RT
    响应时间。
    2)DEGRADE_GRADE_EXCEPTION_RATIO
    异常数比例。
    3)DEGRADE_GRADE_EXCEPTION_COUNT
    异常数量。
  • int rtSlowRequestAmount
    触发 RT 响应熔断出现的最小连续慢响应请求数量。
  • int minRequestAmount
    触发熔断最小的请求数量。
2.2 passCheck方法详解

根据当前请求的情况触发熔断的判断逻辑由 passCheck 方法实现。在介绍这个方法之前,我们根据该方法调用上下文得知,该方法返回 false,则触发熔断。
DegradeRule#passCheck

if (cut.get()) {
    return false;
}

Step1:如果当前正在处于熔断降级中,将直接返回 false,请求将被限流。

DegradeRule#passCheck

ClusterNode clusterNode = ClusterBuilderSlot.getClusterNode(this.getResource());
    if (clusterNode == null) {
        return true;
}

Step2:根据资源名称获得对应的集群类节点,有关集群限流将在后续文章中详细介绍。

DegradeRule#passCheck

if (grade == RuleConstant.DEGRADE_GRADE_RT) {
    double rt = clusterNode.avgRt();
    if (rt < this.count) {
        passCount.set(0);
        return true;
    }
    if (passCount.incrementAndGet() < rtSlowRequestAmount) {
        return true;
    }
}

step3:降级策略为基于响应时间的判断规则,其核心实现关键点:

  • 首先获取节点的平均响应时间。
  • 如果当前平均响应时间小于阔值,则放行,并重置 passCount 为 0。
  • 如果当前平均响应时间大于阔值,但连续次数小于 rtSlowRequestAmount,依然放行,只有当连续 rtSlowRequestAmount 次响应慢才会触发降级。

DegradeRule#passCheck

} else if (grade == RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO) {
    double exception = clusterNode.exceptionQps();
    double success = clusterNode.successQps();
    double total = clusterNode.totalQps();
    if (total < minRequestAmount) {
        return true;
    }
   double realSuccess = success - exception;
    if (realSuccess <= 0 && exception < minRequestAmount) {
        return true;
    }
	if (exception / success < count) {
        return true;
    }
}

Step4:降级策略为根据异常比例,其判断规则核心如下:

  • 分别获取成功QPS,异常QPS,总TPS。
  • 如果当前总 QPS 小于 minRequestAmount,则直接返回成功,表示暂不进行熔断规则判断。
  • 如果成功数小于异常数并且异常数量小于 minRequestAmount,则返回true,表示暂不进熔断规则的判断。
  • 如果异常比例小于阔值,同样返回 true,表示暂不进熔断规则的判断。

DegradeRule#passCheck

else if (grade == RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT) {
    double exception = clusterNode.totalException();
    if (exception < count) {
        return true;
    }        
}

Step5:降级策略为根据异常数量,这策略只是简单的判断错误数量即可。

DegradeRule#passCheck

if (cut.compareAndSet(false, true)) {
    ResetTask resetTask = new ResetTask(this);
    pool.schedule(resetTask, timeWindow, TimeUnit.SECONDS);
}

Step6:如果符合触发熔断的规则,则原子更新 cut,并且开启一个调度任务,在指定时间过后进行降级恢复。

Sentinel 的熔断机制实现比较简单,就介绍到这了,下一篇将介绍 Sentinel 基于集群的限流策略。

好了,我亲爱的读者朋友,以上就是本文的全部内容了,对Sentinel 的熔断实现原理是否已Get。原创不易,莫要白票,请你为本文点赞个吧,这将是我写作更多优质文章的最强动力。


欢迎加笔者微信号(dingwpmz),加群探讨,笔者优质专栏目录:
1、源码分析RocketMQ专栏(40篇+)
2、源码分析Sentinel专栏(12篇+)
3、源码分析Dubbo专栏(28篇+)
4、源码分析Mybatis专栏
5、源码分析Netty专栏(18篇+)
6、源码分析JUC专栏
7、源码分析Elasticjob专栏
8、Elasticsearch专栏(20篇+)
9、源码分析MyCat专栏

Spring Cloud Gateway整合Sentinel实现熔断是为保护服务稳定性,其原理Sentinel特性及Spring Cloud Gateway架构相关。 Sentinel作为Spring Cloud Alibaba提供的微服务组件,具备多维度保护服务稳定性的能力,能从流量控制、熔断降级、系统负载保护等方面守护服务 [^3]。它有丰富应用场景,承接了阿里巴巴近10年双十一大促流量的核心场景,可实时熔断下游不可用应用;还有完备的实时监控功能,能在控制台看到接入应用的单台机器秒级数据,甚至500台以下规模集群的汇总运行情况;具有广泛的开源生态,提供与Spring Cloud等开源框架/库的整合模块;并且有完善的SPI扩展点,方便用户定制逻辑 [^4]。 Spring Cloud Gateway是基于Spring Framework 5、Project Reactor和Spring Boot 2构建的API网关,用于在微服务架构中提供统一的入口。Spring Cloud Gateway整合Sentinel时,Sentinel会对通过网关的请求进行监控和统计。当请求流量达到预设的阈值,如请求响应时间过长、错误率过高等,Sentinel会触发熔断机制,切断对下游服务的请求,避免故障扩散,保护系统的稳定性 [^1][^2][^3]。 当熔断发生后,Sentinel会进入熔断状态,在一段时间内直接返回预设的错误响应,而不将请求转发到下游服务。随着时间推移,Sentinel会尝试恢复对下游服务的请求,若请求恢复正常,熔断状态解除;若仍然异常,继续保持熔断状态。 ```java // 示例代码展示Spring Cloud Gateway整合Sentinel配置 @Configuration public class GatewayConfig { @Bean public RouteLocator customRouteLocator(RouteLocatorBuilder builder) { return builder.routes() .route("path_route", r -> r.path("/api/**") .filters(f -> f.filter(new SentinelGatewayFilter())) .uri("lb://service-name")) .build(); } } ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

中间件兴趣圈

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值