【06】限流熔断降级插件Sentinel

1. Sentinel简介

1.1 背景分析

服务可用性问题

  • 在我们的日常生活中,经常会在淘宝、天猫、京东等平台上参与商品的秒杀、抢购一些优惠商品,也会在节假日使用抢票软件购票,这些场景都会引起服务器流量的暴涨,导致页面无法显示,APP反应慢,功能无法正常运转,甚至会引起整个网站的崩溃。
  • 如果要使这些业务在流量变化无常的情况下,保证各种业务安全的运营,系统在任何情况下都不会崩溃,我们可以在系统负载过高时,采用限流降级熔断三种措施来保护系统,由此一些流量控制中间件诞生了,例如: Sentinel。
  • 服务的可用性场景:
    • 在一个高度服务化的系统中,我们实现的一个业务逻辑通常会依赖多个服务, 如图所示:
      多服务
    • 如果其中的下单服务不可用,就会出现线程池里所有的线程都因等待响应而被阻塞,进而导致整个服务链路不可用,使得整个系统出现服务雪崩。
  • 服务雪崩效应:因服务提供者的不可用,导致服务调用者不可用,并将不可用的过程逐渐放大,就叫做服务雪崩效应。
  • 导致服务不可用的原因:
    服务不可用
    • 在服务提供者不可用的时,会出现大量重试的情况:用户重试、代码逻辑重试,这些重试最终导致进一步加大请求流量。
    • 所以归根结底导致雪崩效应的根本原因是:大量请求,线程同步等待,造成的资源耗尽。当服务调用者使用同步调用时, 会产生大量的等待线程占用系统资源。一旦线程资源被耗尽,服务调用者提供的服务也将处于不可用状态, 于是服务雪崩效应产生了。

1.2 解决方案

1.2.1 超时机制
  • 在不做任何处理的情况下,服务提供者不可用,会导致消费者请求线程强制等待,从而造成系统资源耗尽。如果加入超时机制,一旦超时,就释放资源。由于释放资源速度较快,一定程度上可以抑制资源耗尽的问题。
1.2.2 服务限流
  • 设置每秒最多只允许访问的请求数,只接受一定数据量的请求,而多余的那部分直接拒绝。
  • 主要针对服务提供方(生产者)。
    限流
1.2.3 服务熔断
  • 远程服务不稳定或网络抖动时暂时关闭,就叫服务熔断。
  • 现实世界的断路器大家肯定都很了解,断路器实时监控电路的情况,如果发现电路电流异常,就会跳闸,从而防止电路被烧毁。
  • 软件世界的断路器可以这样理解:实时监测应用,如果发现在一定时间内失败次数/失败率达到一定阈值,就“跳闸”,断路器打开——此时,请求直接返回,而不去调用原本调用的逻辑。跳闸一段时间后(例如10秒),断路器会进入半开状态,这是一个瞬间态,此时允许一次请求调用该调的逻辑,如果成功,则断路器关闭,应用正常调用;
  • 如果调用依然不成功,断路器继续回到打开状态,过段时间再进入半开状态尝试——通过”跳闸“,应用可以保护自己,而且避免浪费资源,而通过半开的设计,可实现应用的自我修复。
  • 所以,同样的道理,当依赖的服务有大量超时时,在让新的请求去访问根本没有意义,只会无畏的消耗现有资源。比如我们设置了超时时间为1s,如果短时间内有大量请求在1s内都得不到响应,就意味着这个服务出现了异常,此时就没有必要再让其他的请求去访问这个依赖的服务,这个时候就应该使用断路器避免资源浪费。
    没必要的服务
1.2.4 服务降级
  • 所谓降级,就是当某个服务熔断之后,服务将不再被调用,此时客户端可以自己准备一个本地的fallback(回退)回调,返回一个缺省值。 例如:(备用接口/缓存/mock数据) 。这样做,虽然服务水平下降,但好歹可用,比直接挂掉要强,当然这也要看适合的业务场景。
  • 主要针对服务调用方(消费者)。

1.3 Sentinel概述

1

  • Sentinel(分布式系统的流量防卫兵)是阿里开源的,面向分布式架构的高可用防护组件,一套用于服务容错的综合性解决方案。它以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度来保护服务的稳定性。
  • Sentinel承接了阿里巴巴近十年双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷,集群流量控制、实时熔断下游不可用应用等。
  • Sentine核心分为两个部分:
    • 核心库(java客户端):能够运行于所有java运行时的环境,同时对Dubbo/Spring Cloud等框架也有较好的支持。
    • 控制台(Dashboard): 基于SpringBoot开发,打包后直接运行。
  • 官网文档

2. 安装Sentinel服务

  • Sentinel提供一个轻量级的控制台,它提供机器发现,单机资源实时监控以及规则管理等功能,其控制台安装步骤如下:
    第一步:打开sentinel下载地址:https://github.com/alibaba/Sentinel/releases
    第二步:下载jar包,如图所示
    1
    第三步:在sentinel对应目录,打开命令行(cmd),启动运行sentinel。

方式1,输入命令:java -Dserver.port=8180 -Dcsp.sentinel.dashboard.server=localhost:8180 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.0.jar
方式2,输入命令:java -Dserver.port=9999 -jar sentinel-dashboard-1.8.0.jar

1

3.访问Sentinel服务

3.1 访问服务

3.1.1 启动Sentinel

在浏览器输入:http://localhost:8180
1

3.1.2 登录Sentinel
  • 登录sentinel,默认用户名和密码都是sentinel,登录成功以后的界面如图所示。
    1
3.1.3 实时监控
  • 监控接口通过的QPS和拒绝的QPS:
    实时监控
3.1.4 簇点链路
  • 用来显示微服务所监控的API:
    簇点链路

3.2 Sentinel限流

3.2.1 概述
  • 系统中的数据库连接池,线程池,nginx的瞬间并发,MQ消息等在使用时都会设定一个限定的值,这本身就是一种限流的设计。限流的目的是防止恶意请求流量、恶意攻击,或者防止流量超过系统的峰值。
3.1.2 Sentinel集成
  • 第一步:Sentinel应用于消费方,在sca-consumers添加依赖。
<!--sentinel限流依赖-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>
        <!--监控依赖(对sentinel暴露一些监控端口)-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
  • 第二步:打开服务消费方配置文件application.yml,添加sentinel配置。
server:
  port: 8091
spring:
  application:
    name: sca-consumer
  cloud:
    nacos:
      disconvery:
        server-addr: localhost:8848  #从哪里去查服务
    sentinel:
      transport:
       dashboard: localhost:8180 #控制台的地址
       port: 8092 #此端口为当前服务与sentinel进行通讯的端口
      eager: true #服务启动时就向sentinel发送消息进行注册
      web-context-unify: true

第三步:启动服务提供者,服务消费者,然后再浏览器访问消费者url.
1
第四步:刷新sentinel控制台,检测服务列表。
1

Sentinel的控制台其实就是一个SpringBoot编写的程序,我们需要将我们的服务注册到控制台上,即在微服务中指定控制台的地址,并且还要在消费端开启一个与sentinel控制台传递数据端的端口,控制台可以通过此端口调用微服务中的监控程序来获取各种信息。

3.3 Sentinel限流快速入门

我们设置一下指定接口的流量控制(流控),QPS(每秒的请求次数),单机阈值为1代表每秒请求不能超过1次,否则就会做限流处理,处理方式直接调用失败。
第一步:选择要限流的链路。
1
第二步:设置限流策略。

第三步:反复刷新访问消费端的服务,检测是否有限流信息输出。

3.4 Sentinel流控规则分析

3.4.1 流量控制
  • 流量控制,其原理就是监控应用流量的QPS或并发线程数等指标,当达到指定的阈值时对流量进行控制,以避免被瞬时的流量高峰冲垮,从而保障应用的高可用性。
    流控1
    流控2
  • 同一个资源可以创建多条限流规则。FlowSlot 会对该资源的所有限流规则依次遍历,直到有规则触发限流或者遍历完所有规则。一条限流规则主要由下面几个因素组成,我们可以组合这些元素来实现不同的限流效果。参考文档
    属性说明
3.4.2 限流阈值类型
  • QPS(Queries Per Second):每秒请求数,即:服务器在一秒内可以处理的请求个数。
    • 进入簇点链路选择具体的访问的API,然后点击流控按钮。
      流控规则配置
  • 并发线程数:并发数控制用于保护业务线程池不被慢调用耗尽。
    • 例如,当应用所依赖的下游应用由于某种原因导致服务不稳定、响应延迟增加,对于调用者来说,意味着吞吐量下降和更多的线程数占用,极端情况下甚至导致线程池耗尽。
    • 为了应对太多线程占用的情况,业内有使用隔离的方案,比如通过不同业务逻辑使用不同线程池来隔离业务自身之间的资源争抢(线程池隔离)。这种隔离方案虽然隔离性比较好,但是代价就是线程数目太多,线程上下文切换的 overhead 比较大,特别是对低延时的调用有比较大的影响。
    • Sentinel 并发控制不负责创建和管理线程池,而是简单统计当前请求上下文的线程数目(正在执行的调用数目),如果超出阈值,新的请求会被立即拒绝,效果类似于信号量隔离。并发数控制通常在调用端进行配置。
    • 可以使用压测工具来测试(JMeter
      流控规则
3.4.3 设置限流模式
  • 基于调用关系的流量控制。调用关系包括调用方、被调用方;一个方法可能会调用其它方法,形成一个调用链路的层次关系。

  • 直接模式:

    • Sentinel默认的流控处理就是【直接 ——> 快速失败】
    • 资源调用达到设置的阈值后直接被流控抛出异常 。
      直接模式
  • 关联模式

    • 当两个资源之间具有资源争抢或者依赖关系的时候,这两个资源便具有了关联。比如对数据库同一个字段的读操作和写操作存在争抢,读的速度过高会影响写得速度,写的速度过高会影响读的速度。如果放任读写操作争抢资源,则争抢本身带来的开销会降低整体的吞吐量。可使用关联限流来避免具有关联关系的资源之间过度的争抢,举例来说,read_db 和 write_db 这两个资源分别代表数据库读写,我们可以给 read_db 设置限流规则来达到写优先的目的:设置 strategy 为 RuleConstant.STRATEGY_RELATE 同时设置 refResource 为 write_db。这样当写库操作过于频繁时,读数据的请求会被限流。
    • 假如URL1是本资源,关联资源是URL2。当关联资源URL2的QPS大于阈值时,就限流本资源URL1接口。
    • 关联模式的应用场景:
      在订单服务中会有两个重要的接口,一个是读取订单信息接口,另一个是写入订单信息接口。在高并发业务场景中,两个接口都会占用资源,如果读取接口访问量过大,就会影响写入接口的性能。业务中如果我们希望写入订单比较重要,那就优先考虑写入订单接口。那就可以利用关联模式,在关联模式上设置写入接口,本资源设置读取接口,这样就会优先写入接口,一旦写入请求过多,就会限制读取的请求。

  • 链路模式

    • 链路模式只记录指定链路入口的流量。当多个服务对指定资源调用时,假如流量超出其设定的阈值,则会进行限流。
      链路
    • 被调用的方法使用@SentinelResource注解指定资源,然后分别在不同的业务方法中对其进行调用。
      假如A业务设置了链路模式的限流,不会影响B业务。
      定义一个资源访问对象(可以直接写在sca-consumer的启动类中)。
       //定义一个资源访问对象
          @Service
          public class ConsunmerService{
           @SentinelResource("doGetResource")
              public String doGetResource (){
                  return "得到资源了!";
              }
          }
      
    • 下面我们在/consumer/doRestEcho1对应的方法中引用ConsumerService中的doGetResource方法。
      
      	 @Autowired
           private ConsunmerService consunmerService;
              
           @GetMapping("/consumer/doRestEcho1")
           public String doRestEcho1() throws InterruptedException {
               consunmerService.doGetResource();
               String url = "http://localhost:8081/provider/echo/" + server;
               //远程调用
              return restTemplate.getForObject(url, String.class);//String.class是调用服务响应数据类型
           }
      
    • 其路由规则配置如下:

      1
    • 注意:流控模式为链路模式时,假如是sentinel 1.7.2以后的版本,Sentinel Web过滤器,默认收敛所有URL的入口。因此链路模式限流则不生效,需要在application.yml添加如下语句来关闭URL PATH聚合。
      sentinel:
           web-context-unify: false
      
    • 修改配置后,重新启动Sentinel,并设置链路流控规则,然后再多次对链路/consumer/doRestEcho1进行访问,检测是否会出现异常。
      链路关联
3.4.4 设置限流效果
  • 快速失败

    • (RuleConstant.CONTROL_BEHAVIOR_DEFAULT)是默认的流量控制方式。
    • 当QPS超过任意规则的阈值后,新的请求就会被立即拒绝,拒绝方式为抛出FlowException。这种方式适用于对系统处理能力确切已知的情况下,比如通过压测确定了系统的准确水位时。
  • WarmUp(预热)

    • (RuleConstant.CONTROL_BEHAVIOR_WARM_UP)方式,即预热/冷启动方式。
    • 当系统长期处于低水位的情况下,当流量突然增加时,直接把系统拉升到高水位可能瞬间把系统压垮。通过"冷启动",让通过的流量缓慢增加,在一定时间内逐渐增加到阈值上限,给冷系统一个预热的时间,避免冷系统被压垮。
    • 冷加载因子: codeFactor 默认是3,即请求 QPS 从 threshold / 3 开始,经预热时长逐渐升至设定的 QPS 阈值。
    • 根据codeFactor(默认3)的值,(阀值 / codeFactor)为初始阈值,经过预热时长,才到达设置的QPS的阈值,假如单机阈值为300,系统初始化的阈值为 30,然后过了10秒,阈值才恢复到300。这个预热的应用场景,如:秒杀系统在开启的瞬间,会有很多流量上来,很有可能把系统打死。预热方式就能很好的保护系统,会慢慢的把流量放进来,慢慢的把阈值增长到设置的阈值。
      在这里插入图片描述
  • 排队等待
    脉冲流量

    • RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER)方式会严格控制请求通过的间隔时间,也就是让请求以均匀的速度通过,对应的是漏桶算法。

    • 阈值类型必须设成QPS,否则无效。并且,暂时不支持 QPS > 1000 的场景。

    • 比如有时候系统在某一个时刻会出现大流量,之后流量就恢复稳定,可以采用这种排队模式,大流量来时可以让流量请求先排队,等恢复了在慢慢进行处理。
      排队等待

3.4.5 小结面试分析
  • Sentinel是什么?(阿里推出一个流量控制平台,防卫兵)
  • 类似Sentinel的产品你知道有什么?(hystrix-一代微服务产品)
  • 你了解哪些限流算法?(计数器、令牌桶、漏斗算法,滑动窗口算法,…)
  • Sentinel 默认的限流算法是什么?(滑动窗口算法)
  • 你了解sentinel中的阈值应用类型吗?(两种-QPS,线程数)
  • Sentinel 限流规则中默认有哪些限流模式?(直连,关联,链路)
  • Sentinel的限流效果有哪些?(快速失败,预热,排队)
  • Sentinel 为什么可以对我们的业务进行限流,原理是什么?
  • 我们在访问web应用时,在web应用内部会有一个拦截器,这个拦截器会对请求的url进行拦截,拦截到请求以后,读取sentinel 控制台推送到web应用的流控规则,基于流控规则对流量进行限流操作。

4. Sentinel熔断降级

4.1 概述

熔断降级

  • 除了流量控制以外,对调用链路中不稳定的资源进行熔断降级也是保障高可用的重要措施之一。由于调用关系的复杂性,如果调用链路中的某个资源不稳定,最终会导致请求发生堆积。
  • 此时,Sentinel 熔断降级会在调用链路中某个资源出现不稳定状态时(例如调用超时或异常比例升高),对这个资源的调用进行限制,让请求快速失败,避免影响到其它的资源而导致级联错误。当资源被降级后,在接下来的降级时间之内,对该资源的调用都自动熔断(默认行为是抛出 DegradeException异常)。
    处理措施

4.2 熔断降级规则

  • 熔断降级规则(DegradeRule)包含下面几个重要的属性:
    熔断降级规则

4.3 熔断降级策略

4.3.1 慢调用比例
  • (SLOW_REQUEST_RATIO):选择以慢调用比例作为阈值,需要设置允许的慢调用 RT(即最大的响应时间),请求的响应时间大于该值则统计为慢调用。
  • 当单位统计时长(statIntervalMs)内请求数目大于设置的最小请求数目,并且慢调用的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。
  • 经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求响应时间小于设置的慢调用 RT 则结束熔断,若大于设置的慢调用 RT 则会再次被熔断。
    慢调用比例
4.3.2 异常比例
  • (ERROR_RATIO):当单位统计时长(statIntervalMs)内请求数目大于设置的最小请求数目,并且异常的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。
  • 经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。异常比率的阈值范围是 [0.0, 1.0],代表 0% - 100%。
    异常比例
4.3.3 异常数
  • (ERROR_COUNT):当单位统计时长内的异常数目超过阈值之后会自动进行熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。
  • 注意:异常降级仅针对业务异常,对 Sentinel 限流降级本身的异常(BlockException)不生效。
    异常数

4.4 准备工作

  • 修改ConsumerController类中的doRestEcho1方法,基于此方法演示慢调用过程下的限流。
      	//AtomicLong类支持线程安全的自增自减操作
        private AtomicLong atomicLong = new AtomicLong(1);
        
      	@GetMapping("/consumer/doRestEcho1")
        public String doRestEcho1() throws InterruptedException {
            //获取自增对象的值,然后再加1
            long num = atomicLong.getAndIncrement();
            if(num%2==0){//模拟50%的慢调用比例
                Thread.sleep(200);
            }
            String url = "http://localhost:8081/provider/echo/" + server;
            //远程调用
            return restTemplate.getForObject(url, String.class);//String.class是调用服务响应数据类型
        }

4.5 Sentinel降级入门

  • 第一步:启动服务后,选择要降级的链路。
    1

  • 第二步:设置降级的规则。

  • 这里表示熔断策略为慢调用比例,表示链路请求数超过3次,假如平均响应时间超过200毫秒的50%时,则对请求进行熔断降级,熔断时间为10秒钟,10秒之后恢复正常。

  • 第三步:对指定链路进行多次刷新,多次访问,假如出现降级熔断,会出现以下结果。
    1

  • 我们也可以进行断点调试,在DefaultBlockExceptionHandler中的handle方法内部加断点,分析异常类型,假如异常类型为DegradeException则为降级熔断。

4.6 Sentinel异常处理

  • 系统提供了默认的异常处理机制,假如默认处理机制不满足我们的需求,我们可以自己进行定义。定义方式上可以直接或间接实现BlockExceptionHandler接口,并将对象交给spring管理。
@Component
public class ServiceBlockExceptionHandler implements BlockExceptionHandler {
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response,BlockException e) throws Exception {
         //response.setStatus(601);
         //设置响应数据的编码
         response.setCharacterEncoding("utf-8");
         //告诉客户端要响应的数据类型以及客户端以什么编码呈现数据
         response.setContentType("text/html;charset=utf-8");
         PrintWriter pw=response.getWriter();
         Map<String,Object> map=new HashMap<>();
         if(e instanceof DegradeException){//降级、熔断
             map.put("status",601);
             map.put("message", "服务被熔断了!");
         }else if(e instanceof FlowException){
             map.put("status",602);
             map.put("message", "服务被限流了!");
         }else{
             map.put("status",603);
             map.put("message", "Blocked by Sentinel (flow limiting)");
         }
         //将map对象转换为json格式字符串
         String jsonStr=new ObjectMapper().writeValueAsString(map);
         pw.println(jsonStr);
         pw.flush();
    }
}

4.7 小结面试分析

  • 何为降级熔断?(让外部应用停止对服务的访问,生活中跳闸,路障设置-此路不通)
  • 为什么要进行熔断呢?(平均响应速度越来越慢或经常出现异常,这样可能会导致调用链堆积,最终系统崩溃)
  • Sentinel中限流,降级的异常父类是谁?(BlockException)
  • Sentinel 出现降级熔断时,系统底层抛出的异常是谁?(DegradeException)
  • Sentinel中异常处理接口是谁?(BlockExceptionHandler)
  • Sentinel中异常处理接口下默认的实现类为? (DefaultBlockExceptionHandler)
  • 假如Sentinel中默认的异常处理规则不满足我们的需求怎么办?(自己定义)
  • 我们如何自己定义Sentinel中异常处理呢?(直接或间接实现BlockExceptionHandler )

5. Sentinel降级策略分析

  • Sentinel熔断降级支持慢调用比例,异常比例,异常数,三种策略。

5.1 慢调用比例

  • 慢调用指耗时大于阈值RT(Response Time)的请求称为慢调用,阈值RT由用户设置。
  • 其属性具体含义说明如下:
  • 慢调用逻辑中的状态分析如下:
    • 熔断(OPEN):请求数大于最小请求数并且慢调用的比率大于比例阈值则发生熔断,熔断时长为用户自定义设置。
    • 探测(HALFOPEN):当熔断过了定义的熔断时长,状态由熔断(OPEN)变为探测(HALFOPEN)。
    • 关闭(CLOSED):如果接下来的一个请求小于最大RT,说明慢调用已经恢复,结束熔断,状态由探测(HALF_OPEN)变更为关闭(CLOSED),如果接下来的一个请求大于最大RT,说明慢调用未恢复,继续熔断,熔断时长保持一致。
    • 注意:Sentinel默认统计的RT上限是4900ms,超出此阈值的都会算作4900ms,若需要变更此上限可以通过启动配置项-Dcsp.sentinel.statistic.max.rt=xxx来配置

5.2 异常比例

  • 当资源的每秒请求数大于等于最小请求数,并且异常总数占通用量的比例超过比例阈值时,资源进入降级状态。其属性说明如下:
  • 异常比例中的状态分析如下:
    • 熔断(OPEN):当请求数大于最小请求并且异常比例大于设置的阈值时触发熔断,熔断时长由用户设置。
    • 探测(HALFOPEN):当超过熔断时长时,由熔断(OPEN)转为探测(HALFOPEN)
    • 关闭(CLOSED):如果接下来的一个请求未发生错误,说明应用恢复,结束熔断,状态由探测(HALF_OPEN)变更为关闭(CLOSED)。如果接下来的一个请求继续发生错误,说明应用未恢复,继续熔断,熔断时长保持一致。

5.3 异常数量

  • 当资源近1分钟的异常数目超过阈值(异常数)之后会进行服务降级。
  • 注意,由于统计时间窗口是分钟级别的,若熔断时长小于60秒,则结束熔断状态后仍可能再次进入熔断状态。其属性说明如下:
  • 基于异常数的状态分析如下:
    • 熔断(OPEN):当请求数大于最小请求并且异常数量大于设置的阈值时触发熔断,熔断时长由用户设置。
    • 探测(HALFOPEN):当超过熔断时长时,由熔断(OPEN)转为探测(HALFOPEN)
    • 关闭(CLOSED):如果接下来的一个请求未发生错误,说明应用恢复,结束熔断,状态由探测 变更为关闭,如果接下来的一个请求继续发生错误,说明应用未恢复,继续熔断,熔断时长保持一致。

5.4 小结面试分析

  • Sentinel 降级熔断策略有哪些?(慢调用,异常比例,异常数)
  • Sentinel 熔断处理逻辑中的有哪些状态?(Open,HalfOpen,Closed)
  • Sentinel 对服务调用进行熔断以后处于什么状态?(熔断打开状态-Open)
  • Sentinel 设置的熔断时长到期以后,Sentinel的熔断会处于什么状态?(探测-HalfOpen,假如再次访问时依旧响应时间比较长或依旧有异常,则继续熔断)
  • Sentinel 中的熔断逻辑恢复正常调用以后,会出现什么状态?(熔断关闭-closed)

6. Sentinel热点规则分析

6.1 概述

  • 何为热点?热点即经常访问的数据。很多时候我们希望统计某个热点数据中访问频次最高的 Top N 数据,并对其访问进行限制。
  • 比如:
    • 商品 ID 为参数,统计一段时间内最常购买的商品 ID 并进行限制。
    • 用户 ID 为参数,针对一段时间内频繁访问的用户 ID 进行限制。
      在这里插入图片描述
  • 热点参数限流会统计传入参数中的热点数据,并根据配置的限流阈值与模式,对包含热点参数的资源调用进行限流。
  • 热点参数限流可以看做是一种特殊的流量控制,仅对包含热点参数的资源调用生效。其中,Sentinel会利用 LRU 策略统计最近最常访问的热点参数,结合令牌桶算法来进行参数级别的流控。

6.2 快速入门

  • 第一步:定义热点业务代码。
//http://localhost:8091/consumer/findById?id=10
@GetMapping("/consumer/findById")
        @SentinelResource("res")
        public String doFindById(@RequestParam("id" )Integer id){
            return "热点数据为:"+id;
        }
  • 注意:

    • 热点规则需要使用@SentinelResource(“resourceName”)注解,否则不生效;
    • 参数必须是7种基本数据类型才会生效
  • 第二步:服务启动后,选择要限流的热点链路。

  • 第三步:增加热点规则。
    在这里插入图片描述

  • 热点规则的限流模式只有QPS模式(这才叫热点)。参数索引为@SentinelResource注解的方法参数下标,0代表第一个参数,1代表第二个参数。单机阈值以及统计窗口时长表示在此窗口时间超过阈值就限流。

  • 第四步:多次访问热点参数方法,检测结果。
    1
    其中,热点参数其实说白了就是特殊的流控,流控设置是针对整个请求的;但是热点参数他可以设置到具体哪个参数,甚至参数针对的值,这样更灵活的进行流控管理。
    一般应用在某些特殊资源的特殊处理,如:某些商品流量大,其他商品流量很正常,就可以利用热点参数限流的方案。

6.3 特定参数设计

  • 注意: 资源名必须是@SentinelResource(value="资源名")中 配置的资源名,热点规则依赖于注解。
  • 这里表示参数值为5时,其阈值为10,其他参数值的阈值为1。
    当访问时,id=5时,其每秒访问超过10次才开始限流,而对于其他参数,每秒访问超过1次就开始限流。

6.4 小结面试分析

  • 如何理解热点数据?(访问频度比较高的数据,某些商品、谋篇文章、某个视频)
  • 热点数据的限流规则是怎样的?(主要是针对参数进行限流设计)
  • 热点数据中的特殊参数如何理解?(热点限流中的某个参数值的阈值设计)
  • 对于热点数据的访问出现限流以后底层异常是什么?(ParamFlowException)

7. Sentinel系统规则

7.1 概述

  • 系统在生产环境运行过程中,我们经常需要监控服务器的状态,看服务器CPU、内存、IO等的使用率;主要目的就是保证服务器正常的运行,不能被某些应用搞崩溃了;而且在保证稳定的前提下,保持系统的最大吞吐量。
  • 长期以来,系统自适应保护的思路是根据硬指标,即系统的负载 (load1) 来做系统过载保护。当系统负载高于某个阈值,就禁止或者减少流量的进入;当 load 开始好转,则恢复流量的进入。

7.2 快速入门

  • Sentinel的系统保护规则是从应用级别的入口流量进行控制,从单台机器的总体 Load、RT、入口 QPS 、线程数和CPU使用率五个维度监控应用数据,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。如图所示
  • 其中:
    • Load(仅对 Linux/Unix-like 机器生效):当系统 load1 超过阈值,且系统当前的并发线程数超过系统容量时才会触发系统保护。系统容量由系统的 maxQps * minRt 计算得出。设定参考值一般是 CPU cores * 2.5。
    • CPU使用率:当系统 CPU 使用率超过阈值即触发系统保护(取值范围 0.0-1.0)。
    • RT:当单台机器上所有入口流量的平均 RT 达到阈值即触发系统保护,单位是毫秒。
    • 线程数:当单台机器上所有入口流量的并发线程数达到阈值即触发系统保护。
    • 入口 QPS:当单台机器上所有入口流量的 QPS 达到阈值即触发系统保护。
  • 系统保护规则是应用整体维度的,而不是资源维度的,并且仅对入口流量生效。入口流量指的是进入应用的流量(EntryType.IN),比如 Web 服务。

7.3 小结面试分析

  • 如何理解sentinel中的系统规则?(是对所有链路的控制规则,是一种系统保护策略)
  • Sentinel的常用系统规则有哪些?(RT,QPS,CPU,线程,Load-linux,unix)
  • Sentinel系统保护规则被触发以后底层会抛出什么异常?(SystemBlockException)

8. Sentinel 授权规则

8.1 概述

  • 很多时候,我们需要根据调用方来限制资源是否通过,这时候可以使用 Sentinel 的黑白名单控制的功能。黑白名单根据资源的请求来源(origin)限制资源是否通过,若配置白名单则只有请求来源位于白名单内时才可通过;若配置黑名单则请求来源位于黑名单时不通过,其余的请求通过。例如微信中的黑名单。

8.2 快速入门

  • sentinel可以基于黑白名单方式进行授权规则设计。

  • 来源访问控制规则(AuthorityRule)非常简单,主要有以下配置项:

    • resource资源名,即限流规则的作用对象。
    • limitApp对应的黑名单/白名单,不同 origin 用 , 分隔,如 appA,appB。
    • strategy限制模式,AUTHORITY_WHITE 为白名单模式,AUTHORITY_BLACK 为黑名单模式,默认为白名单模式。
  • 案例实现

  • 定义请求解析器,用于对请求进行解析,并返回解析结果,sentinel底层 在拦截到用户请求以后,会对请求数据基于此对象进行解析,判定是否符合黑白名单规则。

  • 第一步:定义DefaultRequestOriginParser接口的实现类,基于业务在接口方法中解析请求数据并返回.

/*
  定义请求解析器,用于对请求进行解析,并返回解析结果,sentinel底层在拦截用户请求以后,
  会对请求数据基于此对象进行解析,判定是否符合黑白名单规则。
  方式如下:http://ip:port/consumer/doRestEcho1?origin=app1
  假如参数origin的值在黑名单中,则限制对资源的访问
 */
@Component
public class DefaultRequestOriginParser implements RequestOriginParser {
    @Override
    public String parseOrigin(HttpServletRequest request) {
        //获取请求参数origin的值
        return request.getParameter("origin");
    }
}
  • 第二步:执行资源访问,检测授权规则应用,当我们配置的流控应用值为app1时,假如规则为黑名单,则访问:
    http://localhost:8091//consumer/doRestEcho1?origin=app1。
  • 第三步:设计过程分析。

8.3 小结面试分析

  • 如何理解Sentinel中的授权规则?(对指定资源的访问给出的一种简易的授权策略)
  • Sentinel的授权规则是如何设计的?(白名单和黑名单)
  • 如何理解Sentinel中的白名单?(允许访问的资源名单)
  • 如何理解Sentinel中的黑名单?(不允许访问的资源名单)、
  • Sentinel如何识别白名单和黑名单?(在拦截器中通过调用RequestOriginParser对象的方法检测具体的规则)
  • 授权规则中RequestOriginParser类的做用是什么?(对流控应用值进行解析,检查服务访问时传入的值是否与RequestOriginParser的parseOrigin方法返回值是否相同。)

9. Sentinel持久化模式

  • Sentinel规则的推送有下面三种模式:
    持久化模式

9.1 原始模式

  • 如果不做任何修改,Dashboard 的推送规则方式是通过 API 将规则推送至客户端并直接更新到内存中。
  • 这种做法的好处是简单,无依赖坏处是应用重启规则就会消失,仅用于简单测试,不能用于生产环境。
    原始模式

9.2 拉模式

  • pull 模式的数据源(如本地文件、RDBMS 等)一般是可写入的。使用时需要在客户端注册数据源:将对应的读数据源注册至对应的 RuleManager,将写数据源注册至 transport 的 WritableDataSourceRegistry 中。

9.3 推模式

  • 生产环境下一般更常用的是 push 模式的数据源。对于 push 模式的数据源,如远程配置中心(ZooKeeper, Nacos, Apollo等等),推送的操作不应由 Sentinel 客户端进行,而应该经控制台统一进行管理,直接进行推送,数据源仅负责获取配置中心推送的配置并更新到本地。因此推送规则正确做法应该是 配置中心控制台/Sentinel 控制台配置中心Sentinel 数据源Sentinel,而不是经 Sentinel 数据源推送至配置中心。
9.3.1 基于Nacos配置中心控制台实现推送
  • 引入依赖
    <dependency>
        <groupId>com.alibaba.csp</groupId>
        <artifactId>sentinel-datasource-nacos</artifactId> 
    </dependency>
    
  • nacos配置中心配置流控规则
    [
      {
        "resource": "TestResource",
        "controlBehavior": 0,
        "count": 10.0,
        "grade": 1,
        "limitApp": "default",
        "strategy": 0
      }
    ]
    
    流控规则配置
  • yml中配置
    spring:
      application:
        name: mall-user-sentinel-demo
      cloud:
        nacos:
          discovery:
            server-addr: 127.0.0.1:8848
    
        sentinel:
          transport:
            # 添加sentinel的控制台地址
            dashboard: 127.0.0.1:8080
            # 指定应用与Sentinel控制台交互的端口,应用本地会起一个该端口占用的HttpServer
            port: 8719
          datasource:
            ds1:
              nacos:
                server-addr: 127.0.0.1:8848
                dataId: ${spring.application.name}
                groupId: DEFAULT_GROUP
                data-type: json
                rule-type: flow
    
  • nacos配置中心中添加
    [
        {
            "resource": "userinfo",
            "limitApp": "default",
            "grade": 1,
            "count": 1,
            "strategy": 0,
            "controlBehavior": 0,
            "clusterMode": false
        }
    ]
    

规则配置

  • 引入依赖

     <!--sentinel持久化 采用 Nacos 作为规则配置数据源-->
    <dependency>
        <groupId>com.alibaba.csp</groupId>
        <artifactId>sentinel-datasource-nacos</artifactId>
    </dependency>
    
  • 增加yml配置

server:
  port: 8806

spring:
  application:
    name: mall-user-sentinel-rule-push-demo  #微服务名称

  #配置nacos注册中心地址
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848

    sentinel:
      transport:
        # 添加sentinel的控制台地址
        dashboard: 127.0.0.1:8080
        # 指定应用与Sentinel控制台交互的端口,应用本地会起一个该端口占用的HttpServer
        #port: 8719
      datasource:
#        ds1:   #名称自定义,唯一
#          nacos:
#            server-addr: 127.0.0.1:8848
#            dataId: ${spring.application.name}
#            groupId: DEFAULT_GROUP
#            data-type: json
#            rule-type: flow
        flow-rules:
          nacos:
            server-addr: 127.0.0.1:8848
            dataId: ${spring.application.name}-flow-rules
            groupId: SENTINEL_GROUP   # 注意groupId对应Sentinel Dashboard中的定义
            data-type: json
            rule-type: flow
        degrade-rules:
          nacos:
            server-addr: 127.0.0.1:8848
            dataId: ${spring.application.name}-degrade-rules
            groupId: SENTINEL_GROUP
            data-type: json
            rule-type: degrade
        param-flow-rules:
          nacos:
            server-addr: 127.0.0.1:8848
            dataId: ${spring.application.name}-param-flow-rules
            groupId: SENTINEL_GROUP
            data-type: json
            rule-type: param-flow
        authority-rules:
          nacos:
            server-addr: 127.0.0.1:8848
            dataId: ${spring.application.name}-authority-rules
            groupId: SENTINEL_GROUP
            data-type: json
            rule-type: authority
        system-rules:
          nacos:
            server-addr: 127.0.0.1:8848
            dataId: ${spring.application.name}-system-rules
            groupId: SENTINEL_GROUP
            data-type: json
            rule-type: system

10. 总结

总之,Sentinel可为秒杀、抢购、抢票、拉票等高并发应用,提供API接口层面的流量限制,让突然暴涨而来的流量用户访问受到统一的管控,使用合理的流量放行规则使得用户都能正常得到服务。

10.1 重点分析

  • Sentinel诞生的背景?(计算机的数量是否有限,处理能力是否有限,并发比较大或突发流量比较大)
  • 服务中Sentinel环境的集成,初始化?(添加依赖-两个,sentinel配置)
  • Sentinel 的限流规则?(阈值类型-QPS&线程数,限流模式-直接,关联,链路)
  • Sentinel 的降级(熔断)策略?(慢调用,异常比例,异常数)
  • Sentinel 的热点规则设计(掌握)?
  • Sentinel 系统规则设计?(了解,全局规则定义,针对所有请求有效)
  • Sentinel 授权规则设计?(掌握,黑白名单)

10.2 FAQ分析

  • 为什么要限流?
  • 你了解的那些限流框架?(sentinel)
  • 常用的限流算法有那些?(计数,令牌桶-电影票,漏桶-漏斗,滑动窗口)
  • Sentinel有哪些限流规则?(QPS,线程数)
  • Sentinel有哪些限流模式?(直接,关联-创建订单和查询订单,链路限流-北京六环外不限号,但是五环就限号)
  • Sentinel 的降级(熔断)策略有哪些?(慢调用-响应时长,异常比例-异常占比,异常数)
  • Sentinel 的热点规则中的热点数据?(热卖商品,微博大咖,新上映的电影)
  • 如何理解Sentinel 授权规则中的黑白名单?
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值