1.Sentinel降级

类似于hystrix,Sentinel同样可以和主流的RPC调用框架(openfeign、dubbo)等整合进行服务的降级操作。服务降级通常是基于服务调用者的角度去进行的。当服务提供者出现异常或响应超时时,服务调用者会对相应的服务提供者进行一个降级操作。

2.Sentinel整合OpenFeign降级步骤

1.引入依赖

  1. <!--Sentinel 依赖-->
  2. <dependency>
  3. <groupId>com.alibaba.cloud</groupId>
  4. <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
  5. </dependency>
  6. <!--openfeign 依赖-->
  7. <dependency>
  8. <groupId>org.springframework.cloud</groupId>
  9. <artifactId>spring-cloud-starter-openfeign</artifactId>
  10. </dependency>
  11. <!--openfeign连接池优化 依赖-->
  12. <dependency>
  13. <groupId>io.github.openfeign</groupId>
  14. <artifactId>feign-httpclient</artifactId>
  15. </dependency>

2.编写opefeign客户端

  1. import org.springframework.cloud.openfeign.FeignClient;
  2. import org.springframework.stereotype.Component;
  3. import org.springframework.web.bind.annotation.GetMapping;
  4. import org.springframework.web.bind.annotation.PathVariable;
  5. import org.springframework.web.bind.annotation.RequestParam;
  6. /**
  7. * @author 冯铁城 [fengtiecheng@cyou-inc.com]
  8. * @date 2022-06-10 16:58:53
  9. * @describe:
  10. */
  11. @Component
  12. @FeignClient(value = "sentinel-service")
  13. public interface FeignService {
  14. @GetMapping("/api/v1/sentinel-service/{id}")
  15. String get(@PathVariable Integer id, @RequestParam String name);
  16. }

3.编写降级服务类

  1. import org.springframework.stereotype.Component;
  2. /**
  3. * @author 冯铁城 [fengtiecheng@cyou-inc.com]
  4. * @date 2022-06-10 17:18:25
  5. * @describe:
  6. */
  7. @Component
  8. public class FallbackController implements FeignService{
  9. @Override
  10. public String get(Integer id, String name) {
  11. return "触发降级逻辑";
  12. }
  13. }

4.通过fallback属性声明降级服务类

  1. import org.springframework.cloud.openfeign.FeignClient;
  2. import org.springframework.stereotype.Component;
  3. import org.springframework.web.bind.annotation.GetMapping;
  4. import org.springframework.web.bind.annotation.PathVariable;
  5. import org.springframework.web.bind.annotation.RequestParam;
  6. /**
  7. * @author 冯铁城 [fengtiecheng@cyou-inc.com]
  8. * @date 2022-06-10 16:58:53
  9. * @describe:
  10. */
  11. @Component
  12. @FeignClient(value = "sentinel-service",fallback = FallbackController.class)
  13. public interface FeignService {
  14. @GetMapping("/api/v1/sentinel-service/{id}")
  15. String get(@PathVariable Integer id, @RequestParam String name);
  16. }

5.编写配置文件

  1. feign:
  2. sentinel:
  3. enabled: true
  4. client:
  5. httpclient:
  6. enabled: true # 开启 HttpClient优化连接池
  7. compression:
  8. request:
  9. enabled: true # 开启请求数据的压缩功能
  10. mime-types: text/xml,application/xml, application/json # 压缩类型
  11. min-request-size: 1024 # 最小压缩值标准,当数据大于 1024 才会进行压缩
  12. response:
  13. enabled: true # 开启响应数据压缩功能
  14. ribbon:
  15. ReadTimeout: 2000 #建立连接所用的时间,适用于网络状况正常的情况下,两端两端连接所用的时间
  16. ConnectionTimeout: 2000 #建立连接后,服[[=务器读取到可用资源的时间

6.启动类添加注解

  1. import org.springframework.boot.SpringApplication;
  2. import org.springframework.boot.autoconfigure.SpringBootApplication;
  3. import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
  4. import org.springframework.cloud.openfeign.EnableFeignClients;
  5. @SpringBootApplication
  6. @EnableDiscoveryClient
  7. @EnableFeignClients
  8. public class SentinelConsumerApplication {
  9. public static void main(String[] args) {
  10. SpringApplication.run(SentinelConsumerApplication.class, args);
  11. }
  12. }

3.Sentinel降级说明

服务提供者未进入熔断

  1. 服务提供者超时,触发服务调用者降级逻辑
  2. 服务提供者出现异常,服务提供者资源声明fallback属性,触发服务提供者资源fallback降级逻辑
  3. 服务提供者出现异常,服务提供者资源未声明fallback属性,触发服务调用者降级逻辑

    服务提供者进入熔断

  4. 服务提供者超时/出现异常,服务提供者未声明blockHandler,服务提供者未声明fallback,触发服务调用者降级逻辑

  5. 服务提供者超时/出现异常,服务提供者未声明blockHandler,服务提供者声明fallback,触发服务提供者fallback降级逻辑
  6. 服务提供者超时/出现异常,服务提供者声明blockHandler,服务提供者未声明fallback,触发服务提供者blockHandler降级逻辑
  7. 服务提供者超时/出现异常,服务提供者声明blockHandler,服务提供者声明fallback,触发服务提供者blockHandler降级逻辑

    4.Sentinel的熔断策略

    Sentinel熔断会抛出DegradeException异常,该异常继承BlockException
  • 如果资源声明了blockHandler,那么会被blockHandler捕捉。
  • 如果资源声明了fallback,取决于是否声明了blockHandler,如果声明,那么依旧会被blockHandler捕捉。否则会被fallback捕捉。
  • 如果未声明任何降级逻辑,那么异常会抛出

    慢请求比例(SLOW_REQUEST_RATIO)

    选择以慢调用比例作为阈值,需要设置允许的慢调用 RT(即最大响应时间),若请求的响应时间大于该值则统计为慢调用。
    当单位统计时长(statIntervalMs)内请求数目大于设置的最小请求数目,且慢调用的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。
    经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求响应时间小于设置的慢调用 RT 则结束熔断,若大于设置的慢调用 RT 则再次被熔断。

    异常比例(ERROR_RATIO)

    当单位统计时长(statIntervalMs)内请求数目大于设置的最小请求数目且异常的比例大于阈值,则在接下来的熔断时长内请求会自动被熔断。
    经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。异常比率的阈值范围是 [0.0, 1.0],代表 0% - 100%。

    异常数(ERROR_COUNT)

    当单位统计时长内的异常数目超过阈值之后会自动进行熔断。
    经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。

    5.Sentinel熔断逻辑流程

  1. 当单位统计时长内的请求数超过设定的最小请求数(请求基数超过预期值),并且请求出现的超时比率,异常比率,异常数超过了预期阈值,那么服务进入熔断状态(OPEN)
  2. 熔断状态的时长为熔断时长,即熔断窗口期,在这段时间内,任何请求都走的是熔断的逻辑
  3. 在熔断窗口期结束后,服务进入(HALF_OPEN)状态,检测下一个请求的结果。判定是否超时或出现异常。如果出现异常,那么重新进入熔断逻辑(OPEN),否则熔断状态关闭(CLOSE)

    6.Sentinel熔断状态详解

    | 状态 | 说明 | 触发条件 | | —- | —- | —- | | 熔断关闭状态
    (CLOSED) | 处于关闭状态时,请求可以正常调用资源。 | 满足以下任意条件,Sentinel 熔断器进入熔断关闭状态:
    - 全部请求访问成功。
    - 单位统计时长(statIntervalMs)内请求数目小于设置的最小请求数目。
    - 未达到熔断标准,例如服务超时比例、异常数、异常比例未达到阈值。
    - 处于探测恢复状态时,下一个请求访问成功。
    | | 熔断开启状态
    (OPEN) | 处于熔断开启状态时,熔断器会一定的时间(规定的熔断时长)内,暂时切断所有请求对该资源的调用,并调用相应的熔断逻辑使请求快速失败避免系统崩溃。 | 满足以下任意条件,Sentinel 熔断器进入熔断开启状态:
    - 单位统计时长内请求数目大于设置的最小请求数目,且已达到熔断标准,例如请求超时比例、异常数、异常比例达到阈值。
    - 处于探测恢复状态时,下一个请求访问失败。
    | | 探测恢复状态
    (HALF-OPEN) | 处于探测恢复状态时,Sentinel 熔断器会允许一个请求调用资源。则若接下来的一个请求成功完成(没有错误)则结束熔断,熔断器进入熔断关闭(CLOSED)状态;否则会再次被熔断,熔断器进入熔断开启(OPEN)状态。 | 在熔断开启一段时间(熔断窗口时间或熔断时长,单位为 s)后,Sentinel 熔断器自动会进入探测恢复状态。 |

7.Sentinel实现熔断的过程

Sentinel 实现熔断的步骤如下:

  1. 通过 Sentinel 控制台或代码定义熔断规则,包括熔断策略、最小请求数、阈值、熔断时长以及统计时长等。
  2. 若单位统计时长(statIntervalMs)内,请求数目大于设置的最小请求数目且达到熔断标准(例如请求超时比例、异常数、异常比例达到阈值),Sentinel 熔断器进入熔断开启状态(OPEN)。
  3. 处于熔断开启状态时, @SentinelResource 注解的 blockHandler 属性指定的逻辑会临时充当主业务逻辑,而原来的主逻辑则暂时不可用。当有请求访问该资源时,会直接调用逻辑使请求快速失败,而不会调用原来的主业务逻辑。
  4. 在经过一段时间(在熔断规则中设置的熔断时长)后,熔断器会进入探测恢复状态(HALF-OPEN),此时 Sentinel 会允许一个请求对原来的主业务逻辑进行调用,并监控其调用结果。
  5. 若请求调用成功,则熔断器进入熔断关闭状态(CLOSED ),服务原来的主业务逻辑恢复,否则重新进入熔断开启状态(OPEN)。

    8.Sentinel熔断属性

    | 属性 | 说明 | 默认值 | 使用范围 | | —- | —- | —- | —- | | 资源名 | 规则的作用对象。 | - | 所有熔断策略 | | 统计时长 | 熔断触发需要统计的时长(单位为 ms),如 60*1000 代表分钟级(1.8.0 引入)。 | 1000 ms | 所有熔断策略 | | 最小请求数 | 熔断触发的最小请求数,请求数小于该值时即使异常比率超出阈值也不会熔断(1.7.0 引入)。 | 5 | 所有熔断策略 | | 熔断策略 | Sentinel 支持3 中熔断策略:慢调用比例、异常比例、异常数策略。 | 慢调用比例 | 所有熔断策略 | | 最大 RT | 请求的最大相应时间,请求的响应时间大于该值则统计为慢调用。 | - | 慢调用比例 | | 比例阈值 | 分为慢调用比例阈值和异常比例阈值,即慢调用或异常调用占所有请求的百分比,取值范围 [0.0,1.0]。 | - | 慢调用比例 、异常比例 | | 异常数阈值 | 请求或调用发生的异常的数量。 | - | 异常数 | | 熔断时长 | 熔断开启状态持续的时间,超过该时间熔断器会切换为探测恢复状态(HALF-OPEN),单位为 s。 | - | 所有熔断策略 |

9.Sentinel熔断步骤

1.引入依赖

  1. <!--Sentinel 依赖-->
  2. <dependency>
  3. <groupId>com.alibaba.cloud</groupId>
  4. <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
  5. </dependency>

2.定义资源

  1. import com.alibaba.csp.sentinel.annotation.SentinelResource;
  2. import org.springframework.web.bind.annotation.*;
  3. /**
  4. * @author 冯铁城 [fengtiecheng@cyou-inc.com]
  5. * @date 2022-06-06 14:49:08
  6. * @describe:
  7. */
  8. @RestController
  9. @RequestMapping("/api/v1/sentinel-service")
  10. public class Controller {
  11. @GetMapping("{id}")
  12. public String get(@PathVariable Integer id, @RequestParam String name) {
  13. if (id <= 0) {
  14. throw new RuntimeException("id异常");
  15. }
  16. return id + ":" + name;
  17. }
  18. }

3.定义blockHandlerClass(高优先级)

  1. import com.alibaba.csp.sentinel.slots.block.BlockException;
  2. /**
  3. * @author 冯铁城 [fengtiecheng@cyou-inc.com]
  4. * @date 2022-06-07 10:59:12
  5. * @describe:
  6. */
  7. public class BlockHandlerAll {
  8. public static String get(Integer id, String name, BlockException e) {
  9. System.out.println(e.getMessage()
  10. );
  11. return "服务异常,请稍后尝试";
  12. }
  13. }

4.定义fallbackClass(低优先级)

  1. /**
  2. * @author 冯铁城 [fengtiecheng@cyou-inc.com]
  3. * @date 2022-06-07 10:59:12
  4. * @describe:
  5. */
  6. public class FallbackHandlerAll {
  7. public static String get(Integer id, String name, Throwable t) {
  8. return "服务异常(低优先级),请稍后尝试";
  9. }
  10. }

5.声明资源降级类

  1. import com.alibaba.csp.sentinel.annotation.SentinelResource;
  2. import org.springframework.web.bind.annotation.*;
  3. import java.util.concurrent.TimeUnit;
  4. /**
  5. * @author 冯铁城 [fengtiecheng@cyou-inc.com]
  6. * @date 2022-06-06 14:49:08
  7. * @describe:
  8. */
  9. @RestController
  10. @RequestMapping("/api/v1/sentinel-service")
  11. public class Controller {
  12. @GetMapping
  13. public String get(@RequestParam String param) {
  14. throw new RuntimeException("111111111");
  15. }
  16. @GetMapping("{id}")
  17. @SentinelResource(
  18. value = "get-sentinel-service",
  19. blockHandler = "get",
  20. blockHandlerClass = BlockHandlerAll.class,
  21. fallback = "get",
  22. fallbackClass = FallbackHandlerAll.class
  23. )
  24. public String get(@PathVariable Integer id, @RequestParam String name) throws InterruptedException {
  25. if (id <= 0) {
  26. throw new RuntimeException("id异常");
  27. } else if (id.equals(100)) {
  28. TimeUnit.SECONDS.sleep(3);
  29. }
  30. return id + ":" + name;
  31. }
  32. }

6.控制台配置熔断规则

如图点击降级按钮
1654855273903.png
在弹窗里进行规则配置,然后点击新增即可
如下图参数配置表达的含义:
对consumer-get资源,在1s内如果请求数>=2次,并且出现>=1次异常,会进入10s钟的熔断时间
image.png

7.请求验证

  1. 多次触发异常请求,引导服务进入熔断逻辑
  2. 切换回正常的请求参数,如图,服务进入熔断逻辑

image.png