SpringCloud-Alibaba Sentinel

在这里插入图片描述

一、Sentinel 是什么?

Sentinel: 分布式系统的流量防卫兵

随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。

Sentinel 具有以下特征:

  • 丰富的应用场景:Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、集群流量控制、实时熔断下游不可用应用等。
  • 完备的实时监控:Sentinel 同时提供实时的监控功能。您可以在控制台中看到接入应用的单台机器秒级数据,甚至 500 台以下规模的集群的汇总运行情况。
  • 广泛的开源生态:Sentinel 提供开箱即用的与其它开源框架/库的整合模块,例如与 Spring Cloud、Dubbo、gRPC 的整合。您只需要引入相应的依赖并进行简单的配置即可快速地接入 Sentinel。
  • 完善的 SPI 扩展点:Sentinel 提供简单易用、完善的 SPI 扩展接口。您可以通过实现扩展接口来快速地定制逻辑。例如定制规则管理、适配动态数据源等。

主要特性:

在这里插入图片描述

Sentinel 分为两个部分:

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

二、安装运行

官网

下载地址:https://github.com/alibaba/Sentinel/releases
在这里插入图片描述
运行 (默认端口 8080)

java -jar sentinel-dashboard-1.8.1.jar

在这里插入图片描述
访问 localhost:8080
登录用户与密码都是 sentinel

三、搭建初始化演示工程

搭建项目 8401

项目地址

pom

<dependencies>

        <dependency>
            <groupId>com.yao.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-datasource-nacos</artifactId>
        </dependency>

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

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

yml

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: '*'

cotroller

@RestController
@Slf4j
public class FlowLimitController {

    @GetMapping("/testA")
    public String testA(){
//        try {
//            TimeUnit.SECONDS.sleep(1);
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }
        return "--------testA";
    }

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

    @GetMapping("/testD")
    public String testD(){
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        log.info("testD 测试慢调用比例");
        return "--------testD";
    }

    @GetMapping("/testE")
    public String testE(){
        log.info("testE 测试异常比例");
        int num = 10/0;
        return "--------testE";
    }

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

    @GetMapping("/testHotkey")
    @SentinelResource(value = "testHotkey",blockHandler = "dead_testHotkey")
    public String testHotkey(@RequestParam(value = "p1",required = false) String p1,
                             @RequestParam(value = "p2",required = false) String p2){
        return "------------testHotkey";
    }
    public String dead_testHotkey(String p1, String p2, BlockException blockException){
        return "------------dead_testHotkey";
    }
}

在这里插入图片描述

四、Sentinel 流控(流量控制)规则简介

在这里插入图片描述


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

五、Sentinel 流控 - QPS直接失败

在这里插入图片描述

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

在这里插入图片描述


六、Sentinel 流控 - 线程数直接失败

在这里插入图片描述

当请求A过来访问该接口,该请求处理的很慢,还没有返回数据;此时请求B也过来访问该接口,这个时候处理请求B需要额外开启一个线程,请求B则会报错;

在这里插入图片描述

七、Sentinel 流控 - 关联

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


在这里插入图片描述


应用场景: 比如支付接口达到阈值,就要限流下订单的接口,防止一直有订单产生


八、Sentinel 流控 - 预热(Warm Up)

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

在这里插入图片描述

在这里插入图片描述

表示:默认 coldFactor 为 3,即请求 QPS 从(threshold / 3)开始,经多少预热时长才逐渐升至设定的 QPS 阈值。

案例:阈值为10 + 预热时长设置 5 s
系统初始化的阈值为 10 / 3 约等于 3 ,即阈值刚开始为 3 ,然后经过 5 s后阈值才开始慢慢升高恢复到 10

在这里插入图片描述


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

九、Sentinel 流控 - 排队等待

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

设置含义:/testA 每秒1次请求,超过的话就排队等待,等待的超时时间为 20000 毫秒。

在这里插入图片描述

在这里插入图片描述

十、Sentinel 降级(熔断降级)简介

官方文档


Sentinel 1.8后对熔断降级做了大的调整,可以定义任意时长的熔断时间,引入了半开启恢复支持

Sentinel 默认统计的RT上限是4900ms,超出此阈值的都会算作4900ms,若需要变更此上限可以通过启动配置项-Dcsp.sentinel.statistic.max.rt=xxx来配置

在这里插入图片描述


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 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。

熔断降级规则包含以下几个重要的属性:

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

十一、Sentinel 降级 - 慢调用比例

  • 添加 一个请求
    @GetMapping("/testD")
    public String testD(){
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        log.info("testD 测试慢调用比例");
        return "--------testD";
    }
  • 添加熔断级别
    在这里插入图片描述
    表示强请求相应时间为 200ms,熔断时长 30s,1s 内允许有 5个请求通过

    比例阈值发现设置无效,我设置的 0.5,添加之后就变成 1.

使用 Jmeter 压测

  • 创建一个线程组 1s 发送10 个请求
    在这里插入图片描述

  • 添加 http 请求
    在这里插入图片描述

  • 启动 Jmeter 压测

    在这里插入图片描述

十二、Sentinel 降级 - 异常比例

  • 添加请求

        @GetMapping("/testE")
        public String testE(){
            log.info("testE 测试异常比例");
            int num = 10/0;
            return "--------testE";
        }
    
  • 添加降级规则

    在这里插入图片描述

  • 使用 Jmeter 压测

    在这里插入图片描述

十三、Sentinel 降级 - 异常数

  • 添加请求

     @GetMapping("/testF")
        public String testF(){
            log.info("testE 测试异常数");
            int num = 10/0;
            return "--------testF";
        }
    
  • 添加降级规则
    在这里插入图片描述

  • 测试,不断刷新页面,到第 10 次是就会出现熔断

    在这里插入图片描述

十四、Sentinel 热点参数限流

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

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

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

Sentinel 利用 LRU 策略统计最近最常访问的热点参数,结合令牌桶算法来进行参数级别的流控。热点参数限流支持集群模式。


  • 编写代码

    @GetMapping("/testHotkey")
        @SentinelResource(value = "testHotkey",blockHandler = "dead_testHotkey")
        public String testHotkey(@RequestParam("p1") String p1,@RequestParam("p2") String p2){
            return "------------testHotkey";
        }
        public String dead_testHotkey(String p1, String p2, BlockException blockException){
            return "------------dead_testHotkey";
        }
    
  • 配置
    在这里插入图片描述

    • 测试

    每秒请求次数超过一次,就会触发热点限流(也就是自定义的兜底方法)
    在这里插入图片描述
    不含有第一个参数,不会触发热点限流


参数例外项

在这里插入图片描述
特殊情况:

  • 普通:超过1秒钟一个后,达到阈值 1 后马上被限流
  • 我们期望 p1 参数当它是某个特殊值时,它的限流值和平时不一样
  • 特例:假如当 p1 的值等于 5 ,它的阈值可以达到 200

在这里插入图片描述

  • 测试:当 p1 的值是 5 ,不断刷新,发现并不会进入热点限流

十五、Sentinel 系统自适应限流

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

在这里插入图片描述
系统规则支持以下的模式:

  • 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 达到阈值即触发系统保护。

十六、@SentinelResource 配置

1、按资源名称限流和后续处理
  • 编写 RateLimitController

    @RestController
    public class RateLimitController {
        @GetMapping("/byResource")
        @SentinelResource(value = "byResource",blockHandler = "handleExecption")
        public CommonResult byResource(){
            return new CommonResult(200,"按资源名称限流OK",new Payment(2021L,"serial001"));
        }
    
        public CommonResult handleExecption(BlockException blockException){
            return new CommonResult(444,blockException.getClass().getCanonicalName()+"\t 服务不可用");
        }
    }
    
  • 配置限流规则
    在这里插入图片描述

  • 测试,疯狂刷新页面
    在这里插入图片描述

  • 额外问题:
    此时关闭服务 8401 看看,发现流控规则消失
    在这里插入图片描述

2、按 Url 地址限流和后续处理
  • 添加请求
        @GetMapping("/rateLimit/byUrl")
        @SentinelResource(value = "byUrl")
        public CommonResult byUrl(){
            return new CommonResult(200,"按Url限流OK",new Payment(2021L,"serial002"));
        }
    
  • 配置限流规则
    在这里插入图片描述
  • 测试,疯狂刷新页面
    在这里插入图片描述
3、上面的兜底方案所面临的问题
  • 系统默认的,没有体现我们自己的业务要求
  • 依照现有条件,我们自定义的处理方法又和业务代码耦合在一块,不直观
  • 每个业务方法都添加一个兜底的,那代码膨胀加剧
  • 全局统一的处理方法没有体现
4、客户自定义限流处理逻辑
  • 创建 CustomerBlockHandler 类用于自定义限流处理逻辑

    	public class CustomerBlockHandler {
        public static CommonResult handlerException(BlockException blockException){
            return new CommonResult(444,"按客户自定义,global handlerException---------1");
        }
    
        public static CommonResult handlerException2(BlockException blockException){
            return new CommonResult(444,"按客户自定义,global handlerException----------2");
        }
    }
    
  • 添加请求

    	@GetMapping("/rateLimit/CustomerBlockHandler")
        @SentinelResource(value = "CustomerBlockHandler", blockHandlerClass = CustomerBlockHandler.class, blockHandler = "handlerException")
        public CommonResult CustomerBlockHandler(){
            return new CommonResult(200,"按客户自定义",new Payment(2021L,"serial003"));
        }
    
  • 配置流控规则

    在这里插入图片描述

  • 测试
    在这里插入图片描述

5、更多注解属性说明

@SentinelResource

  • value:
    资源名称,必须项(唯一,不能为空)

  • entryType:
    entry类型,可选项(默认为EntryType.OUT),EntryType.IN 入口流量、EntryType.OUT 出口流量

  • blockHandler/blockHandlerClass:
    blockHandler对应处理BlockException的函数名称可选项.blockHandler函数访问需要public,返回类型需要与原方法相匹配,参数类型需要和原方法相匹配并且最后加一个额外的参数,类型为BlockException.blockHandler 函数默认需要和原方法在同一个类中.若希望使用其他类的函数,则可以指定blockHandlerClass为对应的类的Class对象,注意对应的函数必须为static函数,否则无法解析.

  • fallback:
    fallback函数名称,可选项,用于在抛出异常的时候提供fallback处理逻辑.fallback函数可以针对所有类型的异常(除掉exceptionsToIgnore里面排掉的异常类型)进行处理.

  • fallback函数签名和位置要求:

    • 返回值类型必须与原函数返回值类型一致
    • 方法参数列表需要和原函数一致,或者可以额外多一个Throwable类型的参数用于接收对应的异常。
    • fallback函数默认需要和原方法在同一个类中.若希望使用其他类的函数,则可以指定fallbackClass为对应的类的Class对象,注意对应的函数必须为static函数.
    • defaultFallback(since 1.6.0):
      默认的fallback函数名称,可选项,通常用于通用的fallback逻辑(即可以用于很多服务或方法).默认fallback函数可以针对所有类型的异常(除了exceptionsToIgnore里面排除掉的异常类型)进行处理.若同时配置fallback和defaultFallback,则只有fallback会生效.

    defaultFallback函数签名要求:

    • 返回值类型必须与原函数返回值类型一致
    • 方法参数列表需要为空,或者可以额外多一个Throwable类型的参数用于接收对应的异常.
    • defaultFallback函数默认需要和原方法在同一个类中.若希望使用其他类函数,则可以指定fallbackClass为对应的类Class对象,注意对应的函数必须为static函数.
  • exceptionsToIgnore(since 1.6.0) :
    用于指定那些异常被排除,不会计入异常统计中,也不会进入到fallback逻辑中,而是原样抛出.

十七、Sentinel 服务熔断

Sentinel 整合 ribbon+openFeign+fallback

创建模块 cloudalibaba-provider-payment-9003 、cloudalibaba-provider-payment-9004、cloudalibaba-consumer-nacos-order-84

项目地址

1、Ribbon 系列

若 blockHandler 和 fallback 都进行配置,则被限流降级而抛出的 BlockException 时只会进入 blockHandler 处理逻辑

目的:fallback 管运行时异常,blockHandler 管配置违规


  • 没有任何配置
	@GetMapping("/consumer/paymentSQL/{id}")
    public CommonResult paymentInfo(@PathVariable("id") Long id){
        CommonResult result = restTemplate.getForObject(serverURL + "/paymentSQL/" + id, CommonResult.class, id);
        if (id == 4){
            throw new IllegalArgumentException("非法参数异常....");
        }else if (result.getData() == null){
            throw new NullPointerException("没有该 id 对应的记录.....");
        }

        return  result;
    }

给客户 error 界面,不友好
在这里插入图片描述

  • 只配置fallback
	@GetMapping("/consumer/paymentSQL/{id}")
	@SentinelResource(value = "fallback",fallback = "handlerFallback")  //fallback管理运行时异常
    public CommonResult paymentInfo(@PathVariable("id") Long id){
        CommonResult result = restTemplate.getForObject(serverURL + "/paymentSQL/" + id, CommonResult.class, id);
        if (id == 4){
            throw new IllegalArgumentException("非法参数异常....");
        }else if (result.getData() == null){
            throw new NullPointerException("没有该 id 对应的记录.....");
        }

        return  result;
    }

    public CommonResult handlerFallback(Long id, Throwable e) {
        Payment payment = new Payment(id, null);
        return new CommonResult(444,"兜底异常handlerFallback,exception内容 "+e.getMessage(),payment);
    }

在这里插入图片描述

  • 只配置 blockHandler
	@GetMapping("/consumer/paymentSQL/{id}")
    @SentinelResource(value = "fallback",blockHandler = "handlerBlock")   //blockHandler只负责Sentinel的配置违规
    public CommonResult paymentInfo(@PathVariable("id") Long id){

        CommonResult result = restTemplate.getForObject(serverURL + "/paymentSQL/" + id, CommonResult.class, id);
        if (id == 4){
            throw new IllegalArgumentException("非法参数异常....");
        }else if (result.getData() == null){
            throw new NullPointerException("没有该 id 对应的记录.....");
        }

        return  result;
    }

    public CommonResult handlerBlock(Long id, BlockException e) {
        Payment payment = new Payment(id, null);
        return new CommonResult(445,"blockHandler限流,无此流水: "+e.getMessage(),payment);
    }

为 fallback 添加降级规则:

在这里插入图片描述

访问 http://localhost:84/consumer/paymentSQL/4 会发现运行时异常不会处理。

在这里插入图片描述

点击多次,就会触发降级规则:

在这里插入图片描述

  • fallback 和 blockHandler 都配置
    @GetMapping("/consumer/paymentSQL/{id}")
    @SentinelResource(value = "fallback", fallback = "handlerFallback", blockHandler = "handlerBlock")
    public CommonResult paymentInfo(@PathVariable("id") Long id){

        CommonResult result = restTemplate.getForObject(serverURL + "/paymentSQL/" + id, CommonResult.class, id);
        if (id == 4){
            throw new IllegalArgumentException("非法参数异常....");
        }else if (result.getData() == null){
            throw new NullPointerException("没有该 id 对应的记录.....");
        }

        return  result;
    }

    public CommonResult handlerFallback(Long id, Throwable e) {
        Payment payment = new Payment(id, null);
        return new CommonResult(444,"兜底异常handlerFallback,exception内容 "+e.getMessage(),payment);
    }

    public CommonResult handlerBlock(Long id, BlockException e) {
        Payment payment = new Payment(id, null);
        return new CommonResult(445,"blockHandler限流,无此流水: "+e.getMessage(),payment);
    }

为 fallback 添加流控规则

在这里插入图片描述
正常访问 http://localhost:84/consumer/paymentSQL/1 一秒一次,可以正常访问,如果超过 一秒一次 ,会触发流控规则。

在这里插入图片描述
访问 http://localhost:84/consumer/paymentSQL/4 会发现运行时异常也被处理,多次点击也会触发流控规则

在这里插入图片描述
在这里插入图片描述

2、Feign系列

修改 84 模块 ,84消费者调用提供者 9003 ,feign组件一般是消费侧

pom

 <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
 </dependency>

yml

# 激活 sentinel 对 feign 的支持
feign:
  sentinel:
    enabled: true

PaymentService

@FeignClient(value = "nacos-payment-provider",fallback = PaymentFallbackService.class)
public interface PaymentService {
    @GetMapping("/paymentSQL/{id}")
    CommonResult<Payment> paymentSQL(@PathVariable("id") Long id);
}

兜底方法

@Component
public class PaymentFallbackService implements PaymentService{
    @Override
    public CommonResult<Payment> paymentSQL(Long id) {
        return new CommonResult<>(444,"服务降级返回,----PaymentFallbackService",new Payment(id,"error serial"));
    }
}

controller

@Resource
    private PaymentService paymentService;

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

在这里插入图片描述

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

十八、Sentinel 持久化

演示模块为 8401 模块

  • 为什么要持久化?

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

  • 如何使用?

将限流规则持久化仅 Nacos 保存,只要刷新 8401 某个 rest 地址,sentinel 控制台的流控规则就能看到,只要 Nacos 里面的配置不删除,针对 8401 上的 sentinel 生的流控规则持续有效

  • 正常启动 8401 项目,添加流控规则
    在这里插入图片描述

  • 持久化配置

pom

  <dependency>
      <groupId>com.alibaba.csp</groupId>
      <artifactId>sentinel-datasource-nacos</artifactId>
  </dependency>

yml

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
      datasource:
        ds1:
          nacos:
            server-addr: localhost:8848
            dataId: cloudalibaba-sentinel-service
            groupId: DEFAULT_GROUP
            data-type: json
            rule-type: flow

在 Nacos 中添加配置列表

在这里插入图片描述


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


重启 8401 项目就会发现,流控规则依然存在。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_子栖_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值