一. Sentinel相关概念

1. 雪崩问题及解决

1.1 雪崩问题

一个微服务宕机,其他微服务调用该宕机微服务也会宕机,引起微服务连锁宕机的现象
微服务间调用错综复杂,一个微服务往往依赖于多个微服务

1.2 解决方案

  1. 超时处理
    • 设定超时时间,请求超时则返回错误信息,不用无休止等待
  2. 仓壁模式(线程隔离)
    • 限制每个业务使用的线程数
  3. 熔断降级
    • 使用断路器统计业务执行的异常比例,超过阈值即熔断该业务,拦截访问该业务的一切请求
  4. 流量控制
    • 限制业务访问的QPS

总结

  • 避免高并发流量导致服务故障
    • 流量控制
  • 避免因服务宕机引起的雪崩问题

    • 超时处理
    • 线程隔离
    • 熔断隔离

      二. 流量控制(限流规则)

      簇点链路(项目内调用的链路,链路中被监控的每个接口就是一个资源)
  • 默认情况下Sentinel会监控SpringMVC的每一个端点

  • SpringMVC的每一个端点就是调用链路中的一个资源

    1.流控模式

  1. 直接(默认)
    • 统计当前资源的请求,触发阈值时对当前资源直接限流
  2. 关联
    • 统计与当前资源相关的另一个资源,触发阈值时,对当前资源限流
    • 高优先级资源触发阈值,对低优先级资源限流
  3. 链路
    • 统计从指定链路访问到本资源的请求,触发阈值时,对指定链路限流
    • 只统计从指定资源进入当前资源的请求,是对请求来源的限流

      2. 流控效果

      请求达到流控阈值时应该采用的措施

三种流控效果

  1. 快速失败(默认)
    • 达到阈值后,新的请求会被立即拒绝并抛出FlowException异常
    • QPS超过阈值,拒绝新请求
  2. Warm Up(预热模式)
    • 对超出阈值的请求拒绝并抛出异常
    • 阈值动态变化,从较小值逐渐增大到最大阈值
    • 可以避免冷启动时瞬间高并发导致服务宕机
  3. 排队等待
    • 让所有请求先后次序排队执行,两个请求的间隔不能小于指定时长
    • 请求会进入队列,按照阈值允许的时间间隔依次执行请求;如果请求预期等待的时间大于超时时间,直接拒绝该请求

      3. 热点参数限流

  • 限流是统计访问某个资源的所有请求,判断是否超过QPS阈值
  • 热点参数限流是分别统计参数值相同的请求,判断是否超过QPS阈值

    三. 隔离和降级

    1. 线程隔离

  1. 线程池隔离
    • 基于线程池模式
      • 给每个微服务调用的业务分配一个线程池,利用线程池本身实现隔离效果
    • 优点
      • 隔离控制更强
  2. 信号量隔离(Sentinel默认)
    • 基于计数器模式
      • 不创建线程池,而是计数器模式
      • 记录业务使用的线程数量,达到信号量上显示,禁止新的请求
    • 优点
      • 轻量级
      • 适合高并发场景

        2.熔断降级

  • 由断路器统计服务调用的异常比例,慢请求比例

    • 如果超过阈值则会熔断该服务,即拦截访问该服务的一切请求
    • 而当服务恢复时,熔断器会放行访问该服务的请求

      断路器控制熔断和放行是通过状态机来完成

  • 断路器状态

    • 断路器closed
      • 请求正常
      • 断路器状态关闭,放行所有请求,统计异常比例,慢请求比例
      • 超过阈值则切换到OPEN状态
    • 断路器Open

      • 所有请求直接降级快速失败
      • open状态5秒后会进入half-open
    • 断路器half-open
      • 熔断时间结束,尝试放行一个请求
        • 放行成功则关闭断路器
        • 放行失败则打开断路器

          断路器三种熔断策略

  1. 慢调用
    • 在指定时间内,如果请求数量超过设定的最小数量,慢调用比例大于设定的阈值,则触发熔断
  2. 异常比例
    • 统计指定时间内的调用,如果调用次数超过指定请求数,并且出现异常比例达到设定的比例阈值,则触发熔断
  3. 异常数
    • 统计单位时间内异常的调用次数,超过则触发熔断

      四. 授权规则

      对调用方的来源做控制

授权规则的两种方式

  1. 白名单
    • 来源(origin)在白名单内的调用者允许访问
  2. 黑名单

    • 来源(origin)在黑名单内的调用者不允许访问

      五. 规则持久化

      1. 规则管理模式

  3. 原始模式(Sentinel默认)

    • 将规则保存在内存,重启服务会丢失
  4. pull模式
    • 保存在本地或数据库,定时读取
  5. push模式

    • 保存在nacos,监听变更实时更新

      六. Feign + Sentinel实现服务降级代码实现

      步骤:
  6. 修改application.yml,开启feign的Sentinel功能

    1. feign:
    2. sentinel:
    3. enable: true
  7. 给FeignClient编写调用失败后的降级逻辑

    1. 方式一: FallbackClass
      • 无法对远程调用的异常做处理
    2. 方式二: FallbackFactory(推荐)

      • 可以对远程调用的异常做处理
      1. 编写FallbackFactory逻辑 ```java @Component @Slf4j public class ArticleFeignFallback implements FallbackFactory {

      @Override public ArticleFeign create(Throwable throwable) { return new ArticleFeign() {

      1. @Override
      2. public ResponseResult<ApAuthor> findByUserId(Integer userId) {
      3. log.error("参数:{}", userId);
      4. log.error("文章 findByUserId接口 远程调用失败:{}", throwable.getMessage());
      5. return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR);
      6. }

      } } }

      1. 2. FeignClient注解添加fallbackFactory
      2. ```java
      3. @FeignClient(value = "leadnews-article",
      4. fallbackFactory = ArticleFeignFallback.class)
      5. public interface ArticleFeign {
      6. @GetMapping("/api/v1/author/findByUserId/{userId}")
      7. ResponseResult<ApAuthor> findByUserId(@PathVariable("userId") Integer userId);
      1. Feign配置类添加ComponentScan注解扫描FeignFallbackFactory
        1. @EnableFeignClients(basePackages = "com.heima.feigns",defaultConfiguration = HeimaFeignAutoConfiguration.class)
        2. @Configuration
        3. @ComponentScan("com.heima.feigns.fallback")
        4. public class HeimaFeignAutoConfiguration {
        5. @Bean
        6. Logger.Level level() {
        7. return Logger.Level.FULL;
        8. }
        9. }