Spring Cloud Alibaba Sentinel--分布式系统的流量防卫兵

1 sentinel
1.官网
https://github.com/alibaba/Sentinel
中文:https://github.com/alibaba/Sentinel/wiki/介绍

Hystrix:
1.需要我们程序员自己手工搭建监控平台
2.没有一套web界面可以给我们进行更加细粒度化的配置流控、速率控制、服务熔断、服务降级等
Sentinel:
1.单独一个组件,可以独立出来
2.直接界面化的细粒度统一配置
约定>配置>编码
都可以写在代码里面,但是本次还是大规模的学习使用配置和注解的方式,尽量少写代码

2 是什么
就是之前的Hystrix
Sentinel :分布式系统的流量防卫兵
随着微服务的流行,服务和服务之间的稳定性越来越重要。Sentinel 以流量为切入点,从流量控制、熔断降级、系统保护等等多个维度保护服务的稳定性。
去哪里下:https://github.com/alibaba/Sentinel/releases

3 Sentinel 的特性
Spring Cloud Alibaba Sentinel--分布式系统的流量防卫兵_第1张图片
4 怎么玩

https://spring-cloud-alibaba-group.github.io/github-pages/greenwich/spring-cloud-alibaba.html#_spring_cloud_alibaba_sentinel
服务使用中的各种问题:

服务雪崩
服务降级
服务熔断
服务限流

2 安装Sentinel控制台
1.sentinel组件由两部分构成
Sentinel分为两个不部分(后台和前台8080):

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

2.安装步骤
2.1.下载
https://github.com/alibaba/Sentinel/releases,下载到本地sentinel-dashboard-1.8.2.jar

2.2.运行命令
前提:Java8运行环境正常、8080端口不能被占用
命令:java -jar sentinel-dashboard-1.8.2.jar

2.3.访问sentinel管理界面
http://locahost:8080,登录账户密码均为sentinel

Spring Cloud Alibaba Sentinel--分布式系统的流量防卫兵_第2张图片

3 微服务整合sentinel
1 pom

 <!-- nacos-discovery -->
        <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-datasource-nacos后续做持久化使用 -->
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-datasource-nacos</artifactId>
        </dependency>

2 yml

server:
  port: 8401

spring:
  application:
    name: cloudalibaba-sentinel-service
  cloud:
    nacos:
      discovery:
        #Nacos服务注册中心地址
        server-addr: localhost:8848
    sentinel:
      transport:
        #配置Sentinel dashboard地址
        dashboard: localhost:8080
        #默认8719端口,假如被占用会自动从8719开始依次+1扫描,直到找到未被占用的端口
        port: 8719

management:
  endpoints:
    web:
      exposure:
        include: '*'

3 启动类

在这里插入代码片
@SpringBootApplication
@EnableDiscoveryClient
public class MainApp8401 {
    public static void main(String[] args) {
        SpringApplication.run(MainApp8401.class, args);
    }
}

4 业务类

@RestController
public class FlowLimitController {

    @GetMapping("/testA")
    public String testA() {
        return "--------testA";
    }

    @GetMapping("/testB")
    public String testB() {
        return "--------testB";
    }
}

5 测试
服务都启动后访问sentinel控制台,没有看到任何数据
Sentinel采用的懒加载机制
执行一次访问即可
Spring Cloud Alibaba Sentinel--分布式系统的流量防卫兵_第3张图片
sentinel8080正在监控微服务8401

4 流控规则
4.1.基本介绍
Spring Cloud Alibaba Sentinel--分布式系统的流量防卫兵_第4张图片
资源名:唯一名称,默认请求路径
针对来源:Sentinel可以针对调用者进行限流,填写微服务名,默认default(不区分来源)
阈值类型/单机阈值:
QPS(每秒钟的请求数量):当调用该api的QPS达到阈值的时候,进行限流
线程数:当调用该api的线程数达到阈值的时候,进行限流
是否集群:不需要集群
流控模式:
直接:api达到限流条件时,直接限流
关联:当关联的资源达到阈值时,就限流自己
链路:只记录指定链路上的流量(指定资源从入口资源进来的流量,如果达到阈值,就进行限流)【api级别的针对来源】
流控效果:
快速失败:直接失败,抛异常
Warm Up:根据codeFactor(冷加载因子,默认3)的值,从阈值/codeFactor,经过预热时长,才达到设置的QPS阈值
排队等待:匀速排队,让请求以匀速的速度通过,阈值类型必须设置为QPS,否则无效

4.2 流控模式
1). 直接(默认)
1.1). 直接->快速失败(系统默认)
Spring Cloud Alibaba Sentinel--分布式系统的流量防卫兵_第5张图片

表示1秒钟内查询1次就是OK,如果超过次数1,就直接-快速失败,报默认错误

1.2). 测试
快速点击访问http://localhost:8401/testA,结果出现Blocked by Sentinel (flow limiting)
Spring Cloud Alibaba Sentinel--分布式系统的流量防卫兵_第6张图片
1.3 线程数
Spring Cloud Alibaba Sentinel--分布式系统的流量防卫兵_第7张图片
测试
Spring Cloud Alibaba Sentinel--分布式系统的流量防卫兵_第8张图片

比如a请求过来,处理很慢,在一直处理,此时b请求又过来了,此时因为a占用一个线程,此时要处理b请求就只有额外开启一个线程, 那么就会报错

2). 关联
2.1). 是什么
当与A关联的资源B达到阈值时,就限流A自己,即:B惹事,A挂了
应用场景: 比如支付接口达到阈值,就要限流下订单的接口,防止一直有订单

2.2). 配置A
Spring Cloud Alibaba Sentinel--分布式系统的流量防卫兵_第9张图片

当关联资源/testB的QPS阈值超过1时,就限流/testA的REST访问地址

2.3). postman模拟并发密集访问testB
Spring Cloud Alibaba Sentinel--分布式系统的流量防卫兵_第10张图片
Spring Cloud Alibaba Sentinel--分布式系统的流量防卫兵_第11张图片
先访问testB成功
Spring Cloud Alibaba Sentinel--分布式系统的流量防卫兵_第12张图片
postman里新建多线程集合组,将访问地址添加进新线程组,并运行

Spring Cloud Alibaba Sentinel--分布式系统的流量防卫兵_第13张图片
大批量线程高并发访问B,导致A失效了

2.4). 运行后发现testA挂了
点击访问http://localhost:8401/testA
结果:Blocked by Sentinel (flow limiting)

3). 链路
多个请求调用了同一个微服务

4.3 流控效果
1). 直接->快速失败(默认的流控处理)
直接失败,抛出异常:Blocked by Sentinel (flow limiting)
源码:com.alibaba.csp.sentinel.slots.block.flow.controller.DefaultController
2). 预热
2.1). 说明
公式:阈值除以coldFactor(默认值为3),经过预热时长后才会达到阈值

2.2). 官网
Spring Cloud Alibaba Sentinel--分布式系统的流量防卫兵_第14张图片

默认coldFactor为3,即请求 QPS 从 threshold/3 开始,经过预热时长逐渐升至设定的 QPS 阈值。
限流 冷启动:https://github.com/alibaba/Sentinel/wiki/Flow-Control

2.3). 源码
com.alibaba.csp.sentinel.slots.block.flow.controller.WarmUpController
在这里插入图片描述
2.4). WarmUp配置

默认coldFactor为3,即请求 QPS 从 (threshold/3) 开始,经过预热时长逐渐升至设定的 QPS 阈值。
案例,阈值为10+预热时长设置5秒。
系统初始化的阈值为10/3约等于3,即阈值刚开始为3;然后过了5秒后阈值才慢慢升高恢复到10
Spring Cloud Alibaba Sentinel--分布式系统的流量防卫兵_第15张图片

a. 多次点击http://localhost:8401/testB
刚开始不行,后续慢慢OK

b. 应用场景
如:秒杀系统在开启的瞬间,会有很多流量上来,很有可能把系统打死,预热方式就是为了保护系统,慢慢的把流量放进来,慢慢的把阈值增长到设置的阈值。

3). 排队等待
大家一起去大学食堂排队打饭,大家都是排成一条直线匀速通过

匀速排队,让请求以均匀的速度通过,阈值类型必须设成QPS,否则无效。
设置含义:/testA每秒1次请求,超过的话就排队等待,等待的超时时间为20000毫秒。
Spring Cloud Alibaba Sentinel--分布式系统的流量防卫兵_第16张图片

3.1). 匀速排队,阈值必须设置为QPS

3.2). 官网
Spring Cloud Alibaba Sentinel--分布式系统的流量防卫兵_第17张图片
3.3). 源码
com.alibaba.csp.sentinel.slots.block.flow.controller.RateLimiterController

3.4). 测试
QPS达到阈值,请求排队等待通过
Spring Cloud Alibaba Sentinel--分布式系统的流量防卫兵_第18张图片
5 降级规则
5.1.官网
https://github.com/alibaba/Sentinel/wiki/熔断降级
5.2.基本介绍
Spring Cloud Alibaba Sentinel--分布式系统的流量防卫兵_第19张图片
慢调用比例(秒级)
统计时长内,实际请求数目大于最小请求数目,慢调用比例 > 比例阈值时,触发降级
慢调用:当调用的时间(响应的实际时间)> 设置的RT时,这个调用叫做慢调用
慢调用比例:在所有调用中,慢调用占有实际的比例 = 慢调用次数 / 调用次数
比例阈值:自己设定的,慢调用次数 / 调用次数 = 比例阈值

异常比例(秒级)
QPS>=最小请求数 且异常比例(秒级统计)超过阈值时,触发降级;时间窗口期结束后,关闭降级

异常数(分钟级)
异常数(分钟统计)超过阈值时,触发降级;时间窗口结束后,关闭降级

Sentinel 熔断降级会在调用链路中某个资源出现不稳定状态时(例如调用超时或异常比例升高),对这个资源的调用进行限制,让请求快速失败,避免影响到其它的资源而导致级联错误。
进入熔断状态判断依据:
①当统计时长内,实际请求数目大于最小请求数目,慢调用比例 > 比例阈值 ,进入熔断状态
②熔断状态:在接下来的熔断时长内请求会自动被熔断
③探测恢复状态:熔断时长结束后进入探测恢复状态
④结束熔断:在探测恢复状态,如果接下来的一个请求响应时间小于设置的慢调用 RT,则结束熔断;否则继续熔断。
当资源被降级后,在接下来的降级时间窗口之内,对该资源的调用都自动熔断(默认行为是抛出 DegradeException)。

Sentinel的断路器是没有半开状态的
半开的状态系统自动去检测是否请求有异常,没有异常就关闭断路器恢复使用,有异常则继续打开断路器不可用。
复习Hystrix
Spring Cloud Alibaba Sentinel--分布式系统的流量防卫兵_第20张图片
5.3.降级策略实战
a. 慢调用比例
1). 是什么
慢调用比例 (SLOW_REQUEST_RATIO):选择以慢调用比例作为阈值,需要设置允许的慢调用 RT(即最大的响应时间),请求的响应时间大于该值则统计为慢调用。当单位统计时长(statIntervalMs)内请求数目大于设置的最小请求数目,并且慢调用的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求响应时间小于设置的慢调用 RT 则结束熔断,若大于设置的慢调用 RT 则会再次被熔断。

2). 测试
2.1). 代码

   @GetMapping("/testD")
    public String testD() throws InterruptedException {
        // 暂停几秒钟
        TimeUnit.SECONDS.sleep(1);
        log.info("testD 测试慢调用比例(RT)");
        return "------testD";
    }

2.2). 配置

Spring Cloud Alibaba Sentinel--分布式系统的流量防卫兵_第21张图片
2.3). jmeter压测
①设置线程组
每秒10个请求:
Spring Cloud Alibaba Sentinel--分布式系统的流量防卫兵_第22张图片
②设置测试地址

Spring Cloud Alibaba Sentinel--分布式系统的流量防卫兵_第23张图片
③测试
Ⅰ.运行jmeter线程组
Spring Cloud Alibaba Sentinel--分布式系统的流量防卫兵_第24张图片
Ⅱ.控制台显示
Spring Cloud Alibaba Sentinel--分布式系统的流量防卫兵_第25张图片

Ⅲ.浏览器测试熔断

Spring Cloud Alibaba Sentinel--分布式系统的流量防卫兵_第26张图片
关闭jmeter线程压测,再进行浏览器访问
Spring Cloud Alibaba Sentinel--分布式系统的流量防卫兵_第27张图片
2.4). 结论
Ⅰ.选择以慢调用比例作为阈值,需要设置允许的慢调用 RT(即最大的响应时间),请求的响应时间大于该值则统计为慢调用。当单位统计时长(statIntervalMs)内请求数目大于设置的最小请求数目,并且慢调用的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。
Ⅱ.经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求响应时间小于设置的慢调用 RT 则结束熔断,若大于设置的慢调用 RT 则会再次被熔断。

b. 异常比例
1). 是什么

异常比例 (ERROR_RATIO):当单位统计时长(statIntervalMs)内请求数目大于设置的最小请求数目,并且异常的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。异常比率的阈值范围是 [0.0, 1.0],代表 0% - 100%。

2). 测试
2.1). 代码

 @GetMapping("/testD")
    public String testD() throws InterruptedException {
        log.info("testD 异常比例");
        int age = 10 / 0;
        return "------testD";
    }

2.2). 配置
Spring Cloud Alibaba Sentinel--分布式系统的流量防卫兵_第28张图片
2.3). jmeter压测
Ⅰ.运行jmeter线程组
Spring Cloud Alibaba Sentinel--分布式系统的流量防卫兵_第29张图片
Ⅱ.浏览器测试熔断
Spring Cloud Alibaba Sentinel--分布式系统的流量防卫兵_第30张图片
关闭jmeter线程压测,再进行浏览器访问
Spring Cloud Alibaba Sentinel--分布式系统的流量防卫兵_第31张图片
2.4). 结论

异常比例 (ERROR_RATIO):当单位统计时长(statIntervalMs)内请求数目大于设置的最小请求数目,并且异常的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。异常比率的阈值范围是 [0.0, 1.0],代表 0% - 100%。
按照上述配置,单独访问一次,必然调一次报错一次(int age = 10 / 0)。
开启jmeter后,直接高并发发送请求,多次调用达到我们的配置条件,断路器开启(保险丝跳闸),微服务不可用,不再报错error而是服务降级了。

c. 异常数
1). 是什么
异常数 (ERROR_COUNT):当单位统计时长内的异常数目超过阈值之后会自动进行熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。
时间窗口一定要大于等于60秒。

2). 测试
2.1). 代码

    public String testE() {
        log.info("testE 测试异常数");
        int age = 10 / 0;
        return "------testE";
    }

2.2). 配置
Spring Cloud Alibaba Sentinel--分布式系统的流量防卫兵_第32张图片

2.3). 浏览器测试熔断
第一次访问http://localhost:8401/testE,报错error
Spring Cloud Alibaba Sentinel--分布式系统的流量防卫兵_第33张图片
单位时间秒内连续访问2次,进入熔断后降级
Spring Cloud Alibaba Sentinel--分布式系统的流量防卫兵_第34张图片
6 热点规则(热点key限流)
6.1.基本介绍
Spring Cloud Alibaba Sentinel--分布式系统的流量防卫兵_第35张图片
.6.2.官网
https://github.com/alibaba/Sentinel/wiki/热点参数限流
Spring Cloud Alibaba Sentinel--分布式系统的流量防卫兵_第36张图片
兜底方法
分为系统默认和客户自定义两种
之前的case,限流出现问题后,都是用sentinel系统默认的提示:Blocked by Sentinel(flow limiting)
我们能不能自定义?类似hystrix,某个方法出问题了,就找对应的兜底降级方法?
结论
从HystrixCommand到@SentinelResource

6.3.代码
com.alibaba.csp.sentinel.slots.block.BlockException

   @GetMapping("/testHotKey")
    @SentinelResource(value = "testHotKey", blockHandler = "deal_testHotKey")
    public String testHotKey(@RequestParam(value = "p1", required = false) String p1,
                             @RequestParam(value = "p2", required = false) String p2) {
        return "------testHotKey";
    }

    public String deal_testHotKey(String p1, String p2, BlockException exception) {
        return "------deal_testHotKey,/(ㄒoㄒ)/~~"; //sentinel系统默认的提示:Blocked by Sentinel(flow limiting)
    }

6.4.配置
Spring Cloud Alibaba Sentinel--分布式系统的流量防卫兵_第37张图片
1). @SentinelResource(value = “testHotKey”)
异常达到了前台用户界面看到不友好

2). @SentinelResource(value = “testHotKey”, blockHandler = “deal_testHotKey”)
方法testHotKey里面第一个参数只要QPS超过每秒1次,马上降级处理,使用了我们自定义的降级方法

6.5.测试(对参数索引设置的是0,所以p1做了限流)
❌error

http://localhost:8401/testHotKey?p1=abc
http://localhost:8401/testHotKey?p1=abc&p2=33
✔right
http://localhost:8401/testHotKey?p2=abc

6.6.参数例外项
上述案例演示了第一个参数p1,当QPS超过1秒1次点击后马上被限流
a. 特殊情况
普通:超过1秒钟一个后了,达到阈值1后马上被限流
我们期望p1参数当它是某个特殊值时,它的限流值和平时不一样
特例:假如当p1的值等于5时,它的阈值可以达到200

b. 配置
Spring Cloud Alibaba Sentinel--分布式系统的流量防卫兵_第38张图片
c. 测试
✔ http://localhost:8401/testHotKey?p1=5
❌ http://localhost:8401/testHotKey?p1=3
当p1等于5的时候,阈值变为200
当p1不等于5的时候,阈值就是平常的1

d. 前提条件
热点参数的注意点:参数必须是基本类型或者String

6.7.其它
手贱添加异常:int age = 10/0;

@SentinelResource
处理的是Sentinel控制台配置的违规情况,有blockHandler方法配置的兜底处理;
RuntimeException
int age = 10/0,这个是Java运行时异常RuntimeException,@SentinelResource不管
总结
@SentinelResouce主管配置出错,运行出错该走异常走异常

8.@SentinelResource
1 使用

a. 自定义限流处理类
com.neo.springcloud.alibaba.myhandler.CustomerBlockHandler

public class CustomerBlockHandler {

    public static CommonResult handleException(BlockException exception) {
        return new CommonResult(4444, "按客户自定义,global handlerException------1");
    }
    
    public static CommonResult handleException2(BlockException exception) {
        return new CommonResult(4444, "按客户自定义,global handlerException------2");
    }
}

b. RateLimitController

  @GetMapping("/rateLimit/customerBlockHandler")
    @SentinelResource(value = "customerBlockHandler",
            blockHandlerClass = CustomerBlockHandler.class, blockHandler = "handleException2")
    public CommonResult customerBlockHandler() {
        return new CommonResult(200, "按客户自定义", new Payment(2021L, "serial003"));
    }

c. Sentinel控制台配置
Spring Cloud Alibaba Sentinel--分布式系统的流量防卫兵_第39张图片
更多注解说明
Spring Cloud Alibaba Sentinel--分布式系统的流量防卫兵_第40张图片
2 结合openfeign

#激活SentinelFeign的支持
feign:
  sentinel:
    enabled: true
@FeignClient(value = "nacos-payment-provider", fallback = PaymentFallbackService.class)
public interface PaymentService {

    @GetMapping(value = "/paymentSQL/{id}")
    public CommonResult<Payment> paymentSQL(@PathVariable("id") Long id);
}
@Component
public class PaymentFallbackService implements PaymentService {

    @Override
    public CommonResult<Payment> paymentSQL(Long id) {
        return new CommonResult<>(4444, "服务降级返回,PaymentFallbackService", new Payment(id, "errorSerial"));
    }
}

controller

   @Resource
    private PaymentService paymentService;

    @GetMapping(value = "/consumer/paymentSQL/{id}")
    public CommonResult<Payment> paymentSQL(@PathVariable("id") Long id) {
        return paymentService.paymentSQL(id);
    }

假设:故意关闭9003、9004微服务提供者
测试:测试84调用9003、9004,84消费侧是否自动降级
Spring Cloud Alibaba Sentinel--分布式系统的流量防卫兵_第41张图片
结论:84消费侧会自动降级,不会被耗死

9 熔断框架比较

Sentinel Hystrix
隔离策略 信号量隔离(并发线程数限流) 线程池隔离/信号量隔离
熔断降级策略 基于时间响应、异常比率、异常数 基于异常比率
实时统计实现 滑动窗口(LeapArray) 滑动窗口(基于RxJava)
动态规则配置 支持多种数据源 支持多种数据源
扩展性 多个扩展点 插件形式
基于注解的支持 支持 支持
限流 基于QPS、支持基于调用关系的限流 有限的支持
流量整形 支持预热模式、匀速器模式、预热排队模式 不支持
系统自适应保护 支持 不支持
控制台 提供开箱即用的控制台、可配置规则、查看秒级监控、机器发现等 简单的监控查看

10 规则持久化

一旦我们重启应用,sentinel规则将消失,生产环境需要将配置规则进行持久化
a. 方案

将限流配置规则持久化进Nacos保存,只要刷新8401某个REST地址,sentinel控制台的流控规则就能看到,只要Nacos里面的配置不删除,针对8401上sentinel的流控规则持续有效
b. 步骤
修改cloudalibaba-sentinel-service8401

1). POM

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

2). YML
添加Nacos数据源配置

spring:
  cloud:
    sentinel:
      datasource:
        ds1:
          nacos:
            server-addr: localhost:8848
            dataId: ${spring.application.name}
            groupId: DEFAULT_GROUP
            data-type: json
            rule-type: flow

3). 添加Nacos业务规则配置
Spring Cloud Alibaba Sentinel--分布式系统的流量防卫兵_第42张图片

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

resource: 资源名称
limitApp: 来源应用
grade: 阈值类型,0表示线程数,1表示QPS
count: 单机阈值
strategy: 流控模式,0表示直接,1表示关联,2表示链路
controlBehavior: 流控效果,0表示快速失败,1表示Warm Up2表示排队等待

重新启动8401再看sentinel
乍一看还是没有流控规则
调用http://localhost:8401/rateLimit/byUrl后刷新sentinel,流控规则出现了,持久化验证通过

你可能感兴趣的:(Spring,Cloud,java,spring,cloud,微服务)