• Springcloudalibaba之Sentinel服务熔断与限流


    一、什么是Sentinel?

      它是分布式系统的流量防卫兵,与Hystrix的作用一样,它能保证在某一个服务出现问题的情况下,不会导致整体服务的联级故障,以提高分布式系统的弹性。它是hystrix的替代品。比起hystrix来说,Sentinel可以通过web界面来进行更加细粒度的配置流控、速率控制、服务熔断、服务降级。Sentinel组件由Java客户端和Dashboard构成。sentinel生态圈和主要功能特性如下

       二、Sentinel使用

      1、安装和启动: 去https://github.com/alibaba/Sentinel/releases下载sentinel-dashboard-1.8.2.jar包,运行前需要安装Java8环境,切换到jar包目录cmd执行 java -jar sentinel-dashboard-1.8.2.jar即可启动。访问http://localhost:8080即可显示web控制台登录界面(默认账号密码sentinel)。

       2、创建服务模块

        a.引入jar包

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

        b.修改yml配置文件,配置Sentinel dashboard地址

    server:
      port: 8401
    
    spring:
       application:
           name: cloudalibaba-sentinel-service
       cloud:
           nacos:
              discovery:
                 server-addr: localhost:8848
           sentinel:
               transport:
                   #配置sentinel dashboard地址
                   dashboard: localhost:8080
                  #默认8719端口,假如被占角会自动从8719开始依次+1扫描,直至找到未被占用的端口
                   port: 8719
    
    management:
        endpoints:
           web:
              exposure:
                  include: "*"

        c.编写微服务接口Controller,到此sentinel监控搭建完,访问sentinel控制台,即可显示被监控的8848微服务(sentinel懒加载-需要先调用一次8848服务接口才能显示)。界面如下

    三、Sentinel流控规则

      Sentinel支持流量控制,它监控应用流量的QPS或并发线程数等指标,当达到指定阈值时对流量进行控制,避免系统被瞬时的流量高峰冲垮,保障应用高可用性。

        1.阈值类型:

          QPS:每秒请求数,当前调用该api的QPS到达阈值的时候进行限流。

                线程数:当调用该api的线程数到达阈值的时候,进行限流。

        2.流控模式:

          直接:当api大达到限流条件时,直接限流

          关联:当关联的资源到达阈值,就限流自己

          链路:只记录指定路上的流量,指定资源从入口资源进来的流量,如果达到阈值,就进行限流,api级别的限流

        3.流控效果:

          快速失败:直接返回失败、抛异常

          预热(WarmUP):当系统长期处于低水位的情况下,当流量突然增加时,直接把系统拉升到高水位可能瞬间把系统压垮。通过"冷启动",让通过的流量缓慢增加,在一定时间内逐渐增加到阈值上限,给冷系统一个预热的时间,避免冷系统被压垮。

          排队等待:会严格控制请求通过的间隔时间,也即是让请求以均匀的速度通过,对应的是漏桶算法。

      以下配置界面:

     四、Sentnel熔断降级

      Sentinel熔断降级会在调用链路中某个资源出现不稳定状态时(例如调用超时或异常比例升高),对这个资源的调用进行限制,让请求快速失败,避免影响到其它的资源而导致级联错误。当资源被降级后,在接下来的降级时间窗口之内,对该资源的调用都自动熔断(默认行为是抛出 DegradeException)。Sentinel降级策略包含平均响应时间RT、异常比例、异常数。

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

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

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

      以下是配置界面:

     五、热点参数限流

      热点即经常访问的数据。很多时候我们希望统计某个热点数据中访问频次最高的TopK数据,并对其访问进行限制。比如:·用户ID为参数,针对一段时间内频繁访问的用户ID进行限制。

      热点参数限流会统计传入参数中的热点参数,并根据配置的限流阈值与模式,对包含热点参数的资源调用进行限流。热点参数限流可以看做是一种特殊的流量控制,仅对包含热点参数的资源调用生效。

      1、启用热点参数限流功能:

        a.在服务模块中引入如下依赖:

    <dependency>
        <groupId>com.alibaba.csp</groupId>
        <artifactId>sentinel-parameter-flow-control</artifactId> 
    </dependency>

        b.为对应的资源接口配置热点参数限流规则,在调用的时候传入相应的参数,即可使热点参数限流生效。举例如下:

    @GetMapping("/getHotKey") 
    @SentinelResource(value = "testHotKey" ,blockHandler = "deal_testHotKey")  //blockHandler指定兜底方法,value指定资源名
    public string getHotKey(@RequestParam(value = "p1") string p1,@RequestParam(value = "p2") string p2) 
    {  
      return "------testHotKey" ; 
    }
    public string deal_testHotKey (string p1,string p2,BlockException exception)
    {
      return "------deal_testHotKey,o(T-T)o" ;
    }

         结合以上代码和配置规则,表示:当请求http://localhost:8401/getHotKey?p1=xxxx&p2=xxx资源接口的时候,如果该方法第一个参数每秒的QPS超过1次,就马上降级调用兜底方法deal_testHotKey 。(如果不配置blockHandler,会使用系统默认的兜底方法返回Blocked by Sentinel (flow limiting)或将异常显示到前台,不推荐这样做)

       2、限流规则中参数例外项:在1中,当热点参数是某个特殊值的时候,我们要求不降级限流怎么办?配置规则里提供了参数例外项来解决这个问题,具体如下,通过添加规则组来对每个特殊值添加不同的阈值。 

    六、系统规则

      系统保护规则是从应用级别的入口流量进行控制,从单台机器的load、CPU使用率、平均RT、入口QPS和并发线程数等几个维度监控应用指标,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。系统保护规则是应用整体维度的,而不是资源维度的,并且仅对入口流量生效。入口流量指的是进入应用的流量( EntryType.IN ),比如Web服务或Dubbo服务端接收的请求,都属于入口流量。系统规则支持以下模式:

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

      2、CPU使用率(1.5.0+版本)︰当系统CPU使用率超过阈值即触发系统保护(取值范围0.0-1.0) ,比较灵敏。

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

      4、并发线程数:当单台机器上所有入口流量的并发线程数达到阈值即触发系统保护。

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

      规则配置如图:

     七、自定义限流处理逻辑

      在编码过程中,我们通常需要将业务逻辑与异常处理代码分离,实现解耦。在上面的例子中业务逻辑代码和兜底方法在同一个类中,显然不合适,sentinel提供的注解@SentinelResource注解提供了一个blockHandelClass特性能够方便我们进行代码分离。实现过程如下:

      1、创建一个专门的兜底方法类CustomerBlockHandler

    public class  CustomerBlockHandler
    {
    public static CommonResult handleException(BlockException exception)
    {
    return new CommonResult( code: 200,message:"自定义的限流处理信息");
    }
    public static commonResult handleException2(BlockException exception)
    {
    return new CommonResult( code: 200,message:"自定义的限流处理信息2");
    }
    }

      2、在资源接口方法上增加注解@SentinelResource(value = "customerBlockHandler",blockHandlerclass= CustomerBlockHandler.class,blockHandler = "handleException”)

    @GetMapping("/rateLimit/customerBlockHandler")
    @SentinelResource(value = "customerBlockHandler", blockHandlerclass = customerBlockHandler.class, //指定兜底类
    blockHandler= "handlerException") //指定兜底类中的兜底方法 public commonResult customerBlockHandler()
    {
    return new CommonResult( code: 200,message:"按客户自定义" , new Payment(id: 2020L,serial:."serial003"));
    }

     八、资源接口逻辑异常处理

      前面的@SentinelResource的blockHandler指定方法只用于不满足sentinel控制台配置规则时的兜底,本身并不处理资源接口的异常,该注解提供了另外一个特性fallback,用于指定资源接口内部异常时要执行的兜底方法。例如

    @sentinelResource(value = "fallback" ,fallback = "handlerFallback")  //fallback只负责业务异常
    public commonResult<Payment> fallback(@Pathvariable Long id)
    {
          CommonResult<Payment> result =restTemplate.getForobject(url:SERVICE_URL + "/paymentsQL/"+id ,commonResult.class,id);
        if (id == 4) 
        {
             throw new IllegalArgumentException ("IllegalArgumentException,非法参数异常....");
        }
        return result;
    }

    //业务逻辑异常时执行
    public CommonResult handlerFallback(@Pathvariable Long id, Throwable e) { Payment payment = new Payment(id, serial: "nu1l"); return new CommonResult<>( code: 44, message:"兜底异常FandlerFallback,exception内容"+t .getMessage(), payment); }

      异常忽略:sentinel提供了一个特性exceptionsToIgnore = {illegalArgumentException.class}用于忽略资源接口异常,表示如果触发该类型的异常,就不再用fallback兜底,不会触发降级,让其自行处理后续。

    九、Sentinel规则持久化

      前面的规则配置在微服务重启后会丢失,也就是说他们的配置是临时的,我们需要对这些业务规则进行持久化。我们将限流规则持久化进nacos,只要刷新微服务,就可以看到之前配置的规则。实现方式如下:

      1、在微服务中引入jar包

    <! --Springcloud ailibaba sentinel-datasource-nacos做持久化用到-->
    <dependency>
       <groupid>com.alibaba.csp</ groupId>
      <artifactId>sentinel-datasource-nacos</artifactId>
    </dependency>

      2、yml配置文件中增加nacos数据源配置

    spring:
       cloud:
          sentinel:
             transport:
                 port:8719
              datasource:
                   ds1:
                       nacos:
                          server-addr: localhost:8848
                          datald: ${spring.application.name}
                          groupld: DEFAULT_GROUP
                          data-type: json
                          rule-type: flow

      3、登录nacos控制台配置流控规则:配置列表下新增配置,选json格式,填入如下json代码

    [ 
      {
        "resource":"/rateLimit/byUrl",
        "limitApp": "default",
        "grade": 1,
         "count": 1,
         "clusterMode": false
       }
    ]

      json中内容表示配规则,其中,resource表示资源名,limitApp表示来源应用,grade表示阈值类型-0线程数1QPS,count表示单机阈值,strategy表示流控模式-0直接1关联2链路,controBehavior表示流控效果-0快速失败1Warmup2排队等待,clusterMode表示是否集群。

     
  • 相关阅读:
    WSGI原理
    主从数据库
    mysql高级
    记录
    获取当前时间
    sql注入和防sql注入
    python操作MySQL
    修改Windows10 命令终端cmd的编码为UTF-8
    MySQL查询
    MySQL数据库操作
  • 原文地址:https://www.cnblogs.com/zqhIndex/p/15415815.html
Copyright © 2020-2023  润新知