• 【SpringCloud】八、SpringCloudAlibaba-流量防卫兵Sentinel


    一、 容错思想

    1、场景介绍

    分布式系统里,许多服务之间通过远程调用实现信息交互,调用时不可避免会出现调用失败,比如超时、异常等原因导致调用失败,Sentinel能够保证在一个服务出问题的情况下,不会导致整体服务失败,避免级联故障(服务雪崩),以提高分布式系统的弹性;

    • 比如电商中的用户下订单,我们有两个服务,一个下订单服务,一个减库存服务,
    • 当用户下订单时调用下订单服务,然后下订单服务又调用减库存服务,如果减库 存服务响应延迟或者没有响应,则会造成下订单服务的线程挂起等待,如果大量 的用户请求下订单,或导致大量的请求堆积,引起下订单服务也不可用,如果还 有另外一个服务依赖于订单服务,比如用户服务,它需要查询用户订单,那么用 户服务查询订单也会引起大量的延迟和请求堆积,导致用户服务也不可用。
      所以在微服务架构中,很容易造成服务故障的蔓延,引发整个微服务系统瘫痪不 可用。
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述

    2、常用的容错方案或思想

    1、超时,设置比较短的超时时间,调用不成功,很短时间就释放线程,避免大量线程堵塞等待,导致服务cpu、内存等资源飙高;(快速失败)
    2、限流,超过设置的阈值就拒绝,比如评估系统的QPS是3000,那么就可以设置限流阈值是2800;
    3、仓壁保护,就是一艘船不是一个船舱,而是把一个船舱划分为多个船舱,某个船舱进水了,其他船舱都不受到影响;
    在这里插入图片描述
    4、断路器,熔断器也有叫断路器,他们表示同一个意思,最早来源于微服务之父 Martin Fowler 的论文 CircuitBreaker 一文,“熔断器”本身是一种开关装置,用于在电路上保护线路过载,当线路中有电器发生短路时,能够及时切断故障电路,防止发生过载、发热甚至起火等严重后果。

    二、 What is Sentinel?

    随着微服务的流行,服务与服务之间的调用稳定性变得越来越重要;
    1、当服务访问量达到一定程度,流量扛不住的时候,该如何处理?
    2、服务之间相互依赖,当服务A出现响应时间过长,影响到服务B的响应,进而产生连锁反应,直至影响整个依赖链上的所有服务,该如何处理?
    这是分布式、微服务开发不可避免的问题,Sentinel以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性;
    在这里插入图片描述
    012 年,Sentinel 诞生,主要功能是提供请求流量控制;
    2013-2017 年,Sentinel在阿里巴巴集团内部大量用于生产实践,成为基础技术模块,覆盖了所有的核心场景;
    2018 年,Sentinel 对外开源,并持续演进和版本迭代。
    Sentinel在经过阿里巴巴内部一系列秒杀大促,特别是双11这样电商大促中的锤炼,目前已有不少企业在使用开源版本和云版本的Sentinel,包括顺丰、vivo、每日优鲜、拼多多、易企秀、爱奇艺、融金所、VIPKID、喜马拉雅FM、百融金服等;
    更多使用者:https://github.com/alibaba/Sentinel/issues/18
    按照官方的定义:
    A lightweight powerful flow control component enabling reliability and monitoring for microservices.
    轻量级的流量控制、熔断降级Java 组件,是分布式系统的流量防卫兵;
    Github:https://github.com/alibaba/Sentinel
    在这里插入图片描述

    1、Sentinel主要由两部分组成:

    核心库(Java 客户端):

    Sentinel的核心库不依赖任何第三方框架/库,能够运行于所有 Java环境,同时对 Dubbo / SpringBoot / Spring Cloud 等框架也有很好的支持;

    控制台(Dashboard

    基于 Spring Boot 开发,打包后可以直接运行,不需要额外的 Tomcat 等应用容器;

    三、Spring Cloud Alibaba Sentinel进行容错限流

    Sentinel为springboot程序提供了一个starter依赖,由于sentinel starter依赖默认情况下就会为所有的HTTP服务提供限流埋点,所以在springboot 中的Controller都可以受到Sentinel的保护;
    只需为应用添加 spring-cloud-starter-alibaba-sentinel依赖,所有的HTTP接口都能获得Sentinel保护,当然,我们还需要为Sentinel配置保护的

    1、添加依赖:

    <!--spring-cloud-starter-alibaba-sentinel-->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
    </dependency>
    <!--spring-boot-starter-actuator-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    

    2、配置文件:

    #指定sentinel-dashboard控制台的连接地址
    spring.cloud.sentinel.transport.dashboard=192.168.172.128:8080
    

    3、访问

    我们可以通过访问http://{微服务注册的ip地址}:8719/api接口查看微服务暴露给Sentinel控制台调用的API列表;比如访问:http://localhost:8719/api

    四、Sentinel Dashboard管控台

    Sentinel Dashboard (Sentinel控制台):基于 Spring Boot 开发,是一个单独的应用,打包后可以直接通过spring-boot方式进行启动,不需要额外的 Tomcat 等应用容器,主要提供一个轻量级的控制台,它提供机器发现、单机资源实时监控、集群资源汇总,以及规则管理的功能。
    只需要对应用进行简单的配置,就可以使用这些功能。
    下载官方提供的Sentinel Dashboard的jar包
    https://github.com/alibaba/Sentinel/releases

    启动

    使用如下命令启动编译后的控制台:

    java -jar sentinel-dashboard-1.7.2.jar
    

    ##访问
    登录账号,默认用户名密码都是 sentinel

    Sentinel 会在客户端首次调用的时候进行初始化,开始向控制台发送心跳包,所以要确保客户端有访问量;
    Sentinel Dashboard是一个独立的web应用,可以接受客户端的连接,然后与客户端之间进行通讯,他们之间使用http协议进行通讯,客户端代码需要引入:

    <dependency>
        <groupId>com.alibaba.csp</groupId>
        <artifactId>sentinel-transport-simple-http</artifactId>
        <version>1.6.3</version>
    </dependency>
    

    Spring cloud alibaba如下的依赖已经包含了上面的依赖,所以上面的依赖不需

    <!--spring-cloud-starter-alibaba-sentinel-->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
    </dependency>
    

    五、Sentinel流控规则

    在这里插入图片描述

    • 资源名: 一般是我们的请求路径;
    • 针对来源: 来自于哪个应用;
    • 阈值类型: 分为QPS或线程数;
    • 单机阈值: 单个节点的QPS或线程数阈值;
    • 是否集群: 被请求的服务是否集群部署;

    流控模式:

    (1)直接,就是直接对该资源进行控制;
    (2)关联,关联某一个资源(/app2),被关联的资源/app2达到阈值2,则限制当前资源/test的访问;
    (3)链路,记录指定链路上的流量;

    流控效果:

    (1)快速失败 ,直接限制;
    (2)Warm Up,根据coldFactor(默认为3)的值,从 阈值/coldFactor,经过预热的时长,才达到设置的QPS阈值,比如设置QPS阈值为100,那么100/3 =33,用33作为最初的阈值,然后在10秒到达100后再开始限流;
    (3)排队等待,在QPS阈值到达后,新的请求就等待,直到超时,可以适用于突发流量的请求;

    六、Spring Cloud Alibaba Sentinel降级规则

    在这里插入图片描述
    降级策略:

    (1)RT:

    平均响应时间 (DEGRADE_GRADE_RT),当 1s 内持续进入 N 个请求,对应时刻的平均响应时间(秒级)均超过阈值(count,以 ms 为单位),那么在接下的时间窗口(DegradeRule 中的 timeWindow,以 s 为单位)之内,对这个方法的调用都会自动地熔断(抛出 DegradeException),注意 Sentinel 默认统计的 RT 上限是 4900 ms,超出此阈值的都会算作 4900 ms,若需要变更此上限可以通过启动配置项 -Dcsp.sentinel.statistic.max.rt=xxx 来配置;

    (2)异常比例:

    异常比例 (DEGRADE_GRADE_EXCEPTION_RATIO)是指当资源的每秒异常总数占通过量的比值超过阈值(DegradeRule 中的 count)之后,资源进入降级状态,即在接下的时间窗口(DegradeRule 中的 timeWindow,以 s 为单位)之内,对这个方法的调用都会自动地返回,异常比率的阈值范围是 [0.0, 1.0],代表 0% - 100%;

    (3)异常数:

    异常数 (DEGRADE_GRADE_EXCEPTION_COUNT)是指当资源近1分钟的异常数目超过阈值之后会进行熔断,注意由于统计时间窗口是分钟级别的,若timeWindow小于 60s,则结束熔断状态后仍可能再进入熔断状态;

    七、Spring Cloud Alibaba Sentinel热点规则

    何为热点?热点即经常访问的数据,很多时候我们希望统计某个热点数据中访问频次最高的 Top K 数据,并对其访问进行限制,比如:
    商品 ID 为参数,统计一段时间内最常购买的商品 ID 并进行限制;
    用户 ID 为参数,针对一段时间内频繁访问的用户 ID 进行限制;
    热点参数限流会统计传入参数中的热点参数,并根据配置的限流阈值与模式,对包含热点参数的资源调用进行限流,热点参数限流可以看做是一种特殊的流量控制,仅对包含热点参数的资源调用生效;
    在这里插入图片描述
    热点规则需要使用@SentinelResource(“app”)注解,否则不生效;
    参数必须是7种基本数据类型才会生效;
    热点参数可以对某个具体的热点参数进行限流

    八、Spring Cloud Alibaba Sentinel系统规则

    在这里插入图片描述

    Load,

    Load自适应(仅对Linux/Unix-like机器生效):系统的load1作为启发指标,进行自适应系统保护,当系统load1超过设定的启发值,且系统当前的并发线程数超过估算的系统容量时才会触发系统保护,系统容量由系统的maxQps * minRt估算得出,设定参考值一般是 CPU cores * 2.5;

    平均 RT:

    当单台机器上所有入口流量的平均RT达到阈值即触发系统保护,单位是毫秒;
    并发线程数:当单台机器上所有入口流量的并发线程数达到阈值即触发系统保护;

    入口 QPS:

    当单台机器上所有入口流量的 QPS 达到阈值即触发系统保护;

    CPU usage(1.5.0+ 版本):

    当系统 CPU 使用率超过阈值即触发系统保护(取值范围 0.0-1.0),比较灵敏;

    九、Spring Cloud Alibaba Sentinel授权规则

    实现RequestOriginParser接口,在接口方法中实现区分来源;

    @Component
    public class MyRequestOriginParser implements RequestOriginParser {
        @Override
        public String parseOrigin(HttpServletRequest request) {
            String origin = request.getParameter("origin");
            return origin;
        }
    }
    

    十、Spring Cloud Alibaba Sentinel Dashboard通信原理

    在这里插入图片描述
    微服务暴露给Sentinel Dashboard的API接口列表:http://localhost:8719/api
    懒加载、饥饿加载:
    #true表示饥饿加载
    spring.cloud.sentinel.eager=true
    Sentinel Dashboard控制台配置项,可以修改;
    在这里插入图片描述

    十一、Spring Cloud Alibaba Sentinel三种保护应用方式

    1、直接拦截我们所有controller的请求url路径;

    Sentinel为springboot程序提供了一个starter依赖,由于sentinel starter依赖默认情况下就会为所有的HTTP服务提供限流埋点,所以在springboot 中的Controller都可以受到Sentinel的保护;
    只需为应用添加 spring-cloud-starter-alibaba-sentinel依赖,所有的HTTP接口都能获得Sentinel保护,当然,我们还需要为Sentinel配置保护的规则;
    底层通过一个拦截器对请求url进行拦截:

    com.alibaba.csp.sentinel.adapter.spring.webmvc.SentinelWebInterceptor
    

    可以通过如下配置关闭对微服务的保护:
    #关闭sentinel对controller的url的保护

    spring.cloud.sentinel.filter.enabled=false
    

    2、通过代码方式保护应用;

    GetMapping("/test3/{app}")
    public String test3(@PathVariable("app") String app) {
       System.out.println("/test3/{app} --> " + app);
       Entry entry = null;
       try {
          entry = SphU.entry("test3");
          return restTemplate.getForObject("http://29-nacos-discovery-provider/test", String.class);
       } catch (BlockException e) {
          e.printStackTrace();
          return "熔断降级了...";
       } finally {
          if (entry != null) {
             entry.exit();
          }
       }
    }
    

    3、通过@SentinelResource(value = “app”)注解保护应用;

    在这里插入图片描述

    十二、Spring Cloud Alibaba Sentinel对RestTemplate流控熔断

    #true开启sentinel对resttemplate的支持,false则关闭
    resttemplate.sentinel.enabled=true
    
    
    @SentinelRestTemplate(/*blockHandler="blockA", blockHandlerClass= 
    MyBlockHandlerClass.class*/
            fallback="fallbackA", fallbackClass = MyBlockHandlerClass.class)
    @LoadBalanced //负载均衡
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
    
    @GetMapping("/test2")
    public String test2() {
       return restTemplate.getForObject("http://29-nacos-discovery-provider/test", String.class);
    }
    响应结果对象:SentinelClientHttpResponse;
    

    十三、Spring Cloud Alibaba Sentinel对Feign流控熔断

    #true开启sentinel对feign的支持,false则关闭
    feign.sentinel.enabled=true
    
    @FeignClient(name = "29-nacos-discovery-provider",
            /*fallback = EchoServiceFallback.class,*/
            fallbackFactory = EchoServiceFallbackFactory.class,
            configuration = FeignConfiguration.class)
    public interface EchoService {
        @GetMapping("/notFound")
    String notFound();
    }
    

    十四、Sentinel规则持久化

    (1)原始模式:

    这是默认模式,该模式下规则不持久化,重启微服务,配置的限流降级等规则都丢失;

    (2)Pull模式:

    (拉模式)
    在这里插入图片描述

    如上图所示:sentinel dashboard推送规则给微服务,微服务将规则更新到内存,同时将规则更新到本地文件,以实现规则的持久化;

    (3)Push模式(推模式):

    这种方式是将规则存储在nacos配置中心,微服务从nacos配置中心获取规则,这种方式有更好的实时性和一致性保证,生产环境下一般采用该方式(支持nacos、zookeeper、Apollo等);
    但是目前有一个小问题,当我们在sentinel dashboard控制台更新规则,nacos里面的规则并不能得到更新,后续的版本中可能会解决该问题;
    下面我们分别看一下Pull模式:(拉模式)和Push模式(推模式);

    (4)Pull模式:(拉模式)规则持久化到文件

    1、配置依赖;

    <!--sentinel-datasource-extension数据源扩展-->
    <dependency>
        <groupId>com.alibaba.csp</groupId>
        <artifactId>sentinel-datasource-extension</artifactId>
    </dependency>
    

    2、配置文件;
    暂时不需要配置;
    3、写代码;

    见项目中的 FileDataSourceInit 类;
    

    4、配置SPI;

    resources\META-INF\services\com.alibaba.csp.sentinel.init.InitFunc
    

    Push模式(推模式)规则持久化到Nacos

    (5)Push模式(推模式)规则持久化到Nacos

    1、添加sentinel-datasource-nacos依赖;

    <!--sentinel数据持久化-->
    <dependency>
        <groupId>com.alibaba.csp</groupId>
        <artifactId>sentinel-datasource-nacos</artifactId>
    </dependency>
    

    2、application.properties配置持久化数据源;

    spring.cloud.sentinel.datasource.ds1.nacos.server-addr=192.168.172.128:80
    spring.cloud.sentinel.datasource.ds1.nacos.data-id=${spring.application.name}.json
    spring.cloud.sentinel.datasource.ds1.nacos.group-id=DEFAULT_GROUP
    spring.cloud.sentinel.datasource.ds1.nacos.data-type=json
    spring.cloud.sentinel.datasource.ds1.nacos.rule-type=flow
    

    3、在nacos配置中心配置流控规则;

    [
      {
        "resource": "abc",
        "controlBehavior": 0,
        "count": 1.0,
        "grade": 1,
        "limitApp": "default",
        "strategy": 0
      }
    ]
    
  • 相关阅读:
    AI时代项目经理与架构师的成长之道:ChatGPT让你插上翅膀
    ORACLE分区表学习笔记
    RFID拓展的相关问答
    什么是数据埋点?有何作用?
    Panda3d 动画模型
    Vue后台管理系统项目(33)完成SpuForm照片墙数据的收集
    element ui框架(嵌套路由)
    华为云云耀云服务器L实例评测|基于华为云云耀云服务器L实例搭建EMQX大规模分布式 MQTT 消息服务器场景体验
    自定义hooks函数
    hive判断重复数据连续并分组
  • 原文地址:https://blog.csdn.net/weixin_43333483/article/details/127097264