Sentinel

发布于 2022-04-22  3.46k 次阅读


一,Sentinel概述

  Sentinel和Hystrix一样属于服务降级,服务限流,服务熔断框架,但它功能和性能都更优越于Hystrix,它支持更细粒度化的流量控制,如:配置流控,速率控制等

Sentinel简介:是面向分布式服务架构的流量控制组件,主要以流量为切入点,从流量控制、熔断降级、系统自适应保护等多个维度来帮助您保障微服务的稳定性

sentinel的特点:

  • 丰富的应用场景:Sentinel在阿里巴巴广泛使用,几乎覆盖了近10年双11(11.11)购物节的所有核心场景,比如需要限制突发流量的“秒杀”满足系统容量、消息削峰填谷、下游不可靠服务断路、集群流量控制等
  • 实时监控:Sentinel 还提供实时监控能力。可以实时查看单机运行时信息,500节点以下集群运行时信息汇总
  • 广泛的开源生态系统:Sentinel 提供与 Spring Cloud、Dubbo 和 gRPC 等常用框架和库的开箱即用集成。您只需将适配器依赖项添加到您的服务即可轻松使用 Sentinel
  • 多语言支持:Sentinel 提供了对 Java、Go和C++的原生支持
  • 多种SPI扩展:Sentinel提供易用的SPI扩展接口,让您可以快速自定义您的逻辑,例如自定义规则管理、适配数据源等

Sentinel的基本内容有两个:

  1. 资源:资源是 Sentinel 的关键概念,它可以是 Java 应用程序中的任何内容,例如,由应用程序提供的服务,或由应用程序调用的其它应用提供的服务,甚至可以是一段代码。在接下来的文档中,我们都会用资源来描述代码块,只要通过 Sentinel API 定义的代码,就是资源,能够被 Sentinel 保护起来。大部分情况下,可以使用方法签名,URL,甚至服务名称作为资源名来标示资源
  2. 规则:围绕资源的实时状态设定的规则,可以包括流量控制规则、熔断降级规则以及系统保护规则。所有规则可以动态实时调整。

Sentinel的基本设计理念:流量控制

流量控制有以下几个角度:

  • 资源的调用关系,例如资源的调用链路,资源和资源之间的关系
  • 运行指标,例如 QPS、线程池、系统负载等
  • 控制的效果,例如直接限流、冷启动、排队等

  流量控制在网络传输中是一个常用的概念,它用于调整网络包的发送数据。然而,从系统稳定性角度考虑,在处理请求的速度上,也有非常多的讲究。任意时间到来的请求往往是随机不可控的,而系统的处理能力是有限的。我们需要根据系统的处理能力对流量进行控制。Sentinel 作为一个调配器,可以根据需要把随机的请求调整成合适的形状,如下图所示:

二,Sentinel控制台安装

Sentinel分为两个部分:

  1. 核心库(java客户端)不依赖任何框架/库,能够运行于所有Java运行时环境,同时对Dubbo/SpringCloud等框架有较好的支持
  2. 控制台(Dashboard)基于Spring Boot开发,打包后可以直接运行,不需要额外的Tomcat等应用容器

控制台下载地址:https://github.com/alibaba/Sentinel/releases

运行前的注意事项:

  • 需要JDK环境
  • 默认端口是8080,假如被占用(1,停掉占用端口的应用  2,修改端口)

运行命令:

java -jar sentinel-dashboard-1.8.2.jar

访问:

三,客户端使用Sentinel

① maven依赖

<!--实现服务的注册与发现-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

<!--sentinel服务限流降级框架-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>

<!--sentinel持久化依赖包-->
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-datasource-nacos</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

② application配置

server:
  port: 9106
spring:
  application:
    name: cloudalibaba-SentinelMain-service
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.68.134:8084 #nacos服务端地址,Nginx做了代理
    sentinel:
      transport:
        dashboard: localhost:8080 #SentinelMain dashboard地址
        port: 8719 #默认端口为8719,如果被占用开始+1扫描,直到找到未被占用的端口

③ main启动类

@SpringBootApplication
@EnableDiscoveryClient
public class SentinelMain {

    public static void main(String[] args) {
        SpringApplication.run(SentinelMain.class,args);
    }}

④ controller

@RestController
public class sentinelcontroller {

    @GetMapping("/testA")
    public String test1(){

        return "------> testA";
    }

    @GetMapping("/testB")
    public String test2(){

        return "------> testB";
    }
}

服务/testA(因为Sentinel是懒加载),查看Sentinel DashBoard

四,Sentinel流控规则

Sentinel提供了可视化的流量控制界面,使用此界面可以流量控制

1,资源名:唯一名称,默认为请求路径

2,针对来源:Sentinel可以针对调用者进行限流,填写微服务名称即可,默认default(不区分来源)

3,阈值类型和单机阈值

  • QPS(每秒请求数量):当接口的QPS的达到阈值,进行限流
  • 并发线程数:当调用该接口的线程数达到阈值,进行限流

4,是否集群:不需要集群

5,流控模式

  • 直接:当API接口达到限流条件时直接限流
  • 关联:当关联的资源达到阈值,就限制自己
  • 链路:只记录指定链路上的流量(指定资源从入口资源进入的流量,如果达到阈值就进行限流)

6,流控效果

  • 快速失败:默认模式,直接失败抛异常
  • Warm up:根据codeFactor(冷加载因子默认为3),从阈值codeFactor,经过预热时长,才达到设置的QPS阈值
  • 等待排队:匀速排队,让请求匀速通过,阈值必须设置为QPS,否则无效

一,直接失败

直接失败:

  • QPS达到阈值直接失败
  • 线程数达到阈值直接失败

测试:

二,关联

当关联的资源达到阈值时,就限流自己,当与A关联的资源B达到阈值后,就限流A自己

① 设置

②测试:使用Postman发送并发请求给/testB,用浏览器测试/testA是否能访问

当/testB的并发量降到2时,/testA又可以恢复访问

三,预热(Warm Up)

  Warm Up即预热/启动方式,当系统长时间处于低流量的情况下,当流量突然增加,直接把系统拉升到高水位可能瞬间把系统拉跨,通过"冷启动",让通过流量缓慢增加,在一定时间内逐步增加到阈值上限,给冷系统1一个预热的时间,避免冷系统被瞬间拉垮

具体的例子参见 WarmUpFlowDemo

公式:阈值除以coldFactor(默认为3),经过预热时长后才达到阈值

默认coldFactor为3,即请求QPS从theshold/3开始,经过预热时长逐步升至设定的QPS阈值

使用场景如秒杀系统在开启瞬间,会有很多流量上来,很可能把系统压垮,预热方式就是为了保护系统,慢慢把流量放进来

四,排队等待

匀速排对,让请求以均匀的速度通过,阀值类型必须设置成QPS,否则无效

匀速排对方式会严格控制请求通过的间隔时间,也即是让请求以匀速通过。对应的是漏桶算法

  这种方式主要用于处理间隔性突发的流量,例如消息队列。想象一下这样的场景,在某一秒有大量的请求到来,而接下来的几秒则处于空闲状态,我们希望系统能够在接下来的空闲期间逐渐处理这些请求,而不是在第一秒直接拒绝多余的请求

设置:/testA每秒2次请求,超过的话就排队等待,等代时间为2000毫秒

五,Sentinel服务熔断降级

一,Sentinel服务降级的概述

Sentinel的服务降级本质上和Hystrix是一样的,只不过比Hystrix降级的规则和可选项更多

Sentinel熔断降级会在调用链路中某个资源出现不稳定状态时(如:调用超时或异常比例升高),对这个资源的调用进行限制,让请求快速失败,避免影响其他资源而导致级联错误

官网定义:除了流量控制以外,对调用链路中不稳定的资源进行熔断降级也是保障高可用的重要措施之一。一个服务常常会调用别的模块,可能是另外的一个远程服务、数据库,或者第三方 API 等。例如,支付的时候,可能需要远程调用银联提供的 API;查询某个商品的价格,可能需要进行数据库查询。然而,这个被依赖服务的稳定性是不能保证的。如果依赖的服务出现了不稳定的情况,请求的响应时间变长,那么调用服务的方法的响应时间也会变长,线程会产生堆积,最终可能耗尽业务自身的线程池,服务本身也变得不可用

二,服务降级的策略和规则

Sentinel 提供以下几种熔断策略:

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

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

Field 说明 默认值
resource 资源名,即规则的作用对象  
grade 熔断策略,支持慢调用比例/异常比例/异常数策略 慢调用比例
count 慢调用比例模式下为慢调用临界 RT(超出该值计为慢调用);异常比例/异常数模式下为对应的阈值  
timeWindow 熔断时长,单位为 s  
minRequestAmount 熔断触发的最小请求数,请求数小于该值时即使异常比率超出阈值也不会熔断(1.7.0 引入) 5
statIntervalMs 统计时长(单位为 ms),如 60*1000 代表分钟级(1.8.0 引入) 1000 ms
slowRatioThreshold 慢调用比例阈值,仅慢调用比例模式有效(1.8.0 引入)

三,Sentinel服务熔断降级的使用

一,慢调用比例

在慢调用比例之前是RT,Sentinel在RT的基础上做了增强形成了慢调用比例

选择以慢调用比例作为阈值,需要设置允许的慢调用 RT(即最大的响应时间),请求的响应时间大于该值则统计为慢调用

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

  •  最大RT:请求最大的响应时间
  • 比例阈值:[0.0,1.0]之间,分别为0%~100%
  • 熔断时长:就是窗口时间,当熔断降级后的恢复时间
  • 最小请求数:当请求大于这个数,才其余慢调用比例
  • 统计时长:请求在一个时间段内进行统计,判断每个请求响应时间是否大于RT,假如大于的比例超过比例阈值就进行熔断

① 设置:

② /testA的代码:设置休眠时间

@GetMapping("/testA")
public String test1(){
    try {
        Thread.sleep(500);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return "------> testA";
}

③ 测试:通过Jmeter发送1000个并发请求,通过流量器查看是否能继续访问

二,异常比例

  当资源的每秒请求量大于或者等于最小请求数,并且每秒异常总数占比大于比例阈值,资源就会进入降级状态,即在接下来的熔断时长(时间窗口)之内对这个方法的调用都会自动返回,比例阈值在[0.1,1]之间

① 设置

② /testA的代码:设置一个异常

@GetMapping("/testA")
public String test1(){
   
    int a=10/0;
    return "------> testA";
}

③ 测试:jmeter发送并发请求

注:假如请求量小于3没有触发异常比例熔断就会直接报错

三,异常数

当资源请求异常在统计时间中大于异常数阈值就直接进行熔断

① 设置

② /testA的代码:设置一个异常(和上面一样)

③ 测试:jmeter发送并发请求

六,Sentinel热点参数限流

何为热点?热点即经常访问的数据,很多时候我们希望统计某个热点数据中访问频次最高的 Top K 数据,并对其访问进行限制。比如:

  • 商品 ID 为参数,统计一段时间内最常购买的商品 ID 并进行限制
  • 用户 ID 为参数,针对一段时间内频繁访问的用户 ID 进行限制

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

一,sentinel客户端代码配置

Sentinel依赖与@SentinelResource进行定义热点规则兜底方法和定义唯一ID

@GetMapping("/testHotKey")
/*
* 1,value:值必须唯一之后在服务端可以使用它来做资源的唯一标识
* 2,blockHandler:但触发了限流规则使用那个方法进行兜底
* */
@SentinelResource(value = "testHotKey",blockHandler = "reveal")
public String testHotKey(@RequestParam(value = "p1",required = false) String p1,
                         @RequestParam(value = "p2",required = false) String p2) {//定义两个参数

   return "----------ToHetKey---------";
}


//兜底方法必须要和原方法参数一致,可以加一个异常变量
public String reveal(String p1, String p2, BlockException e){


    return "热点限流/(ㄒoㄒ)/~~";
}

二,sentinel服务端进行热点限流

设置:

设置的含义:假如消费者或者用户调用/testHotKey接口并携带p1参数,QPS超过3就进行热点限流(不携带该热点参数就不会被限流)

三,参数例外项

在上面的案例演示中携带p1,QPS超过三就立马被限流,不会区别参数的值只注重是否携带了该热点参数

参数例外项针对的是特殊情况,更注重参数的值实现更加细粒度的规则,如:当携带的p1参数值为3时提高或者减少阈值

设置:

七,Sentinel的系统自适应限流

Sentinel 系统自适应限流从整体维度对应用入口流量进行控制,结合应用的 Load、CPU 使用率、总体平均 RT、入口 QPS 和并发线程数等几个维度的监控指标,通过自适应的流控策略,让系统的入口流量和系统的负载达到一个平衡,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性

系统的自适应限流是应用整体维度,而不是资源维度的,并且仅对入口流量生效,入口流量指的是进入应用的流量,比如:Web服务或者Dubbo服务端接收的请求都属于入口流量

系统规则支持以下模式:

  • Load 自适应(仅对 Linux/Unix-like 机器生效):系统的 load1 作为启发指标,进行自适应系统保护。当系统 load1 超过设定的启发值,且系统当前的并发线程数超过估算的系统容量时才会触发系统保护(BBR 阶段)。系统容量由系统的 maxQps * minRt 估算得出。设定参考值一般是 CPU cores * 2.5
  • CPU usage(1.5.0+ 版本):当系统 CPU 使用率超过阈值即触发系统保护(取值范围 0.0-1.0),比较灵敏
  • 平均 RT:当单台机器上所有入口流量的平均 RT 达到阈值即触发系统保护,单位是毫秒。
  • 并发线程数:当单台机器上所有入口流量的并发线程数达到阈值即触发系统保护
  • 入口 QPS:当单台机器上所有入口流量的 QPS 达到阈值即触发系统保护

注:这种设置方式在开发中一般不使用,细度太低,一般更多的还是从资源和热点的角度进行限流

设置:

设置之后,只要访问应用,它的QPS就不能大于2,否则就限流

 


路漫漫其修远兮,吾将上下而求索