Sentinel核心源码分析(下)


前言

  在上篇中,主要记录了Sentinel与Spring Boot的整合,以及责任链的构建,执行的过程。在责任链中,与规则校验,熔断降级有关的主要是最后四个节点:AuthoritySlot、SystemSlot、FlowSlot、DegradeSlot。在校验不通过,或者触发熔断降级时,通常会抛出异常:
  AuthoritySlot抛出的是AuthorityException
在这里插入图片描述
  SystemSlot抛出的是SystemBlockException
在这里插入图片描述
  FlowSlot抛出的是FlowException
在这里插入图片描述
  DegradeSlot抛出的是DegradeException
在这里插入图片描述
  这四个Sentinel自定义的异常,都有一个共同点,是BlockException的子类。抛出的异常,又会被责任链中的StatisticSlot节点捕获,并执行一系列的逻辑,然后继续向上抛出。
在这里插入图片描述
  最后会被最外层的SentinelResourceAspect切面捕获:
在这里插入图片描述

一、StatisticSlot的异常处理

  在责任链的StatisticSlot节点中,执行完后续责任链的代码,实际上还会进行一些资源的处理,例如增加当前线程调用数,后续规则校验通过的请求数:
在这里插入图片描述
  在捕捉到了后续四个责任链节点抛出的BlockException后,StatisticSlot会统计被规则限流的调用数量,然后继续向上抛出异常。
在这里插入图片描述

二、SentinelResourceAspect的异常处理

  SentinelResourceAspect的异常处理,分为两部分,即处理BlockExceptionThrowable
在这里插入图片描述
  BlockException是不符合规则,或者熔断降级之后抛出的异常,会被@SentinelResource注解中的blockHandler所标注的方法进行处理:
在这里插入图片描述
通过反射调用

  Throwable的异常,是用户的业务代码抛出的异常,由@SentinelResource注解中的blockHandler所标注的方法进行处理:
在这里插入图片描述
通过反射调用

三、entry.exit

  在SentinelResourceAspect切面中,无论是否出现异常,entry.exit是一定会执行的方法。该方法会逐个调用责任链节点的exit方法:
在这里插入图片描述
每个责任链节点都有exit方法

  NodeSelectorSlotClusterBuilderSlotAuthoritySlotSystemSlotFlowSlot的exit方法都是直接调用下一个节点,LogSlot则是记录日志,重点是StatisticSlotDegradeSlot

2.1、StatisticSlot的exit

  在StatisticSlot的exit中,首先会获取链路中的当前节点:
在这里插入图片描述
  如果 BlockError 为 null,说明这次请求是通过了限流校验的,才进行后续统计,并且会用当前时间 - 创建时间,统计出该次请求的调用时间:
在这里插入图片描述
  然后会获取请求中的其他错误信息,并且记录完成统计(响应时间、成功数、异常数):recordCompleteFor方法
在这里插入图片描述
  recordCompleteFor方法
在这里插入图片描述

  • 记录响应时间,以及调用完成数
    在这里插入图片描述
  • 释放线程数
    在这里插入图片描述

2.2、DegradeSlot的exit

  DegradeSlot的exit方法,会获取链路中的当前资源访问记录:
在这里插入图片描述
  如果之前已经被拦截(限流/熔断等),直接调用下一个 Slot 的 exit()。**这种情况说明该请求已经被熔断降级了,熔断器处于open状态,不需要更新状态。**没有熔断规则,说明这个资源不需要熔断逻辑,也会直接调用下一个 Slot 的 exit():
在这里插入图片描述
  能走到这一步,说明本次请求是正常通过的,可能存在两种情况:

  1. 本身熔断器没有触发熔断,处于关闭状态。
  2. 熔断器熔断时间已过,本次请求是熔断时长结束后的下一个请求。

在这里插入图片描述
  有两个不同的实现,分别是ExceptionCircuitBreaker ResponseTimeCircuitBreaker 前者对应调用异常数比例,后者对应慢调用比例。
在这里插入图片描述
  在ResponseTimeCircuitBreakeronRequestComplete方法中,如果请求处理时间大于阈值,则慢调用数量 + 1,无论是否超过阈值,总调用次数都会 + 1。
在这里插入图片描述
  然后会调用handleStateChangeWhenThresholdExceeded处理熔断器状态,如果熔断器已经处于打开的状态,就无需处理,直接结束。
在这里插入图片描述
  然后是处理半开状态:

  • 本次调用的时间,大于阈值,则熔断器重新开启。更新熔断时间
  • 本次调用的时间,小于等于阈值,则熔断器关闭。重置慢调用和总调用次数为0

在这里插入图片描述
  无论是开启还是关闭,都是CAS操作,并且会通知观察者执行自己的逻辑(也就是用户可以自定义熔断器状态变化时执行的逻辑)
在这里插入图片描述
在这里插入图片描述
  最后的这段逻辑,是处理熔断器关闭的情况。如果慢调用的比例超过了阈值,则会打开熔断器。
在这里插入图片描述
  ExceptionCircuitBreaker是同样的道理,只不过统计的维度成为了异常比例。

总结

  在 Sentinel 的异常体系中,主要分为两类:

  1. 第一类是继承了 BlockException 的异常,通常由限流、熔断降级等规则触发,表示“资源访问被拒绝”;
  2. 第二类是用户程序在执行过程中产生的运行时异常,例如空指针、业务异常等。

  Sentinel 的异常处理主要体现在 StatisticSlotSentinelResourceAspect 中。前者用于统计异常信息,并将异常抛出;后者则负责实际处理这些异常,通常通过用户在注解中配置的回调方法处理:

  • 对于继承了 BlockException 的异常,会被 @SentinelResource 注解中的 blockHandler 方法处理;
  • 对于用户代码中的异常(非 BlockException),则由 @SentinelResource 注解中的 fallback 方法进行兜底处理。

  上述处理逻辑最终都是通过反射机制调用用户定义的方法完成的。


  此外,在 Sentinel 的责任链中,除了 entry 方法用于进入资源,还存在一个用于资源释放的 exit 方法,常见的 Slot 有两个关键实现:

  • StatisticSlotexit 方法用于统计调用完成数、响应时间、异常信息等,并释放当前线程数;
  • DegradeSlotexit 方法则主要用于更新熔断器状态。Sentinel 提供了两类熔断策略:异常比率熔断慢调用比率熔断
    • 如果当前熔断器处于“打开(OPEN)”状态,则不会进行任何更新;
    • 如果熔断器处于“半开(HALF_OPEN)”状态:
      • 若本次调用异常,或响应时间超过阈值,熔断器重新转为打开状态,并更新熔断时间;
      • 若调用正常,且响应时间未超过阈值,则熔断器进入关闭(CLOSED)状态,并重置统计数据;
    • 若熔断器处于“关闭(CLOSED)”状态,若检测到异常比例或慢调用比例超过阈值,则触发熔断,状态转为“打开”。

  在这一过程中,Sentinel 也采用了观察者模式,允许用户注册监听器,在熔断器状态发生变化时执行自定义逻辑(如报警、日志等)。

下一篇:Sentinel核心算法解析

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值