欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

荐 SpringCloud Alibaba Sentinel(史上最详细)

程序员文章站 2022-03-26 14:47:58
Sentinel: 分布式系统的流量防卫兵一.Sentinel简介二.Sentinel安装与使用1.下载2.启动3.登录4.初始化演示工程三.Sentinel规则1.流控规则1.1 流控模式①直接②关联③链路1.2 流控效果①快速失败②Warm Up③排队等待2.降级规则2.1 RT(平均响应时间)2.2 异常比例2.3 异常数3.热点key规则4.系统规则四.@SentinelResource注解的详细使用1.按资源名称限流+后续处理2.按照Url地址限流+后续处理3.客户自定义限流处理逻辑五.服务熔断功...

一.Sentinel简介

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

说白了,就是对SpringCloud Hystrix进一步的优化,大多数是参照Hystrix的核心理念的,前面我们也详解了Hystrix,对本篇博客理解有很大的帮助

Sentinel 具有以下特征:

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

Sentinel 的主要特性:
荐
                                                        SpringCloud Alibaba Sentinel(史上最详细)
Sentinel 分为两个部分:

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

二.Sentinel安装与使用

1.下载

官网下载
由于官网下载巨慢,所以我为大家准备了,请自取
链接:https://pan.baidu.com/s/1I6QzjrHSHQ9J5d516njdzg
提取码:30bj

2.启动

前提:java8环境ok、8080端口不能被占用
进入下载好的目录,打开cmd,输入命令java -jar sentinel-dashboard-1.7.1.jar启动Sentinel即可
荐
                                                        SpringCloud Alibaba Sentinel(史上最详细)

3.登录

浏览器输入:localhost:8080,即可访问
荐
                                                        SpringCloud Alibaba Sentinel(史上最详细)
默认账号密码都是sentinel,登录成功,安装完成!
荐
                                                        SpringCloud Alibaba Sentinel(史上最详细)

4.初始化演示工程

  • 先创建一个工程,让sentinel可以检测到

pom.xml:

<dependencies>
        <!--引入自己的定义的包-->
        <dependency>
            <groupId>com.baidu</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>
        <!--nacos-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!-- sentinel做持久化配置-->
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-datasource-nacos</artifactId>
        </dependency>
        <!--引入sentinel-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>
        <!--引入OpenFeign-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <!--引入web相关-->
        <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>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>4.6.3</version>
        </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>

application.yml:

server:
  port: 8401

spring:
  application:
    name: cloudalibaba-sentinel-service
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 #Nacos服务注册中心地址
    sentinel:
      transport:
        dashboard: localhost:8080 #配置Sentinel dashboard地址
        port: 8719
        
management:
  endpoints:
    web:
      exposure:
        include: '*'

主启动类:

@EnableDiscoveryClient
@SpringBootApplication
public class MainApp8401
{
    public static void main(String[] args) {
        SpringApplication.run(MainApp8401.class, args);
    }
}

业务类controller:

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

    @GetMapping("/testB")
    public String testB() {
        return "------testB";
    }
}
  • 启动测试
    测试工程
    荐
                                                        SpringCloud Alibaba Sentinel(史上最详细)
    荐
                                                        SpringCloud Alibaba Sentinel(史上最详细)
    可以看到sentinel已经对8401的工程进行监控
    荐
                                                        SpringCloud Alibaba Sentinel(史上最详细)

三.Sentinel规则

1.流控规则

荐
                                                        SpringCloud Alibaba Sentinel(史上最详细)

1.资源名: 唯一名称,默认请求路径,表示对该资源进行流控
2. 针对来源: Sentinel可以针对调用者进行限流,填写微服务名,默认default(不区分来源)
3. 阈值类型/单击阈值:

  • QPS(每秒钟的请求数量):当调用该api的QPS达到阈值时,进行限流
  • 线程数:当调用该线程数达到阈值的时候,进行限流

4.是否集群:不需要集群
5.流控模式:

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

6.流控效果:

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

下面就详细解释流控模式和流控效果

1.1 流控模式

①直接

直接: api达到限流条件时,直接限流
荐
                                                        SpringCloud Alibaba Sentinel(史上最详细)
这个时候如果在一秒内快速点击/testA,就会发现直接调用了默认的报错信息
荐
                                                        SpringCloud Alibaba Sentinel(史上最详细)
关于QPS和线程数的解释:

QPS是每秒钟的请求数量,而线程数是每秒钟的线程数。
举个银行的例子,银行要受理业务,如果按QPS来说,就是每秒让1个客户进门受理,按线程数来说,就是每秒可以让很多客户进门并且办理业务,但是银行只开了1个窗口办理业务

②关联

关联: 当关联的资源达到阈值时,就限流自己
举个例子,淘宝的流程是先下订单,后支付,所以如果当支付接口承受不了高并发的压力,就会让订单接口限流,这样都得到了缓解
荐
                                                        SpringCloud Alibaba Sentinel(史上最详细)
使用jmeter模拟并发访问testB
荐
                                                        SpringCloud Alibaba Sentinel(史上最详细)
这时候访问testA,已经被限流了
荐
                                                        SpringCloud Alibaba Sentinel(史上最详细)

③链路

链路: 只记录指定链路上的流量(指定资源从入口资源进来的流量,如果达到阈值,就进行限流)【api级别的针对来源】
上面的话不太好理解,实际上,链路的控制指的就是对一条链路的访问进行控制,比方说a—>b—>是一条链路,假设我以a为入口资源,d为终点资源,对这条链路进行限制的话,则资源a,b,d均会被限制访问。
荐
                                                        SpringCloud Alibaba Sentinel(史上最详细)
荐
                                                        SpringCloud Alibaba Sentinel(史上最详细)
此时1秒内快速点击testA,会触发限流

1.2 流控效果

①快速失败

快速失败: 直接失败,抛异常,默认的流控处理,上述全部是快速失败的例子,就不多说了

②Warm Up

Warm Up: 即预热/冷启动方式。当系统长期处于低水位的情况下,当流量突然增加时,直接把系统拉升到高水位可能瞬间把系统压垮。通过“冷启动”,让通过的流量缓慢增加,在一定时间内逐渐增加到阈值上限,给冷系统一个预热的时间,避免冷系统被压垮
应用场景: 秒杀系统在开启的瞬间,会有很多流量上来,很有可能把系统打死,预热方式就是为了保护系统,可以慢慢的把流量放进来,慢慢的把阈值增长为设置的阈值
公式: 默认coldFactor为3,即请求QPS从设定的阈值/3开始,经预热时长逐渐升至设定的QPS阈值
荐
                                                        SpringCloud Alibaba Sentinel(史上最详细)
测试得到,快速点击testA,一开始点击3次,会限流,等预热后,没有限流了,因为手速就跟不上1秒6次啦,哈哈

③排队等待

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

匀速排队方式会严格控制请求通过的间隔时间,也即是让请求以均匀的速度通过,对应的是漏桶算法。
这种方式主要用于处理间隔性突发的流量,例如消息队列。想象一下这样的场景,在某一秒有大量的请求到来,而接下来的几秒则处于空闲状态,我们希望系统能够在接下来的空闲期间逐渐处理这些请求,而不是在第一秒直接拒绝多余的请求。

荐
                                                        SpringCloud Alibaba Sentinel(史上最详细)
为了测试观察方便,在testB方法中加入日志打印,方便观察

 @GetMapping("/testB")
    public String testB() {
        log.info(Thread.currentThread().getName()+"testB...");
        return "------testB";
    }

用postman发送请求
荐
                                                        SpringCloud Alibaba Sentinel(史上最详细)
看看后台日志打印,说明是排队等待的效果!
荐
                                                        SpringCloud Alibaba Sentinel(史上最详细)

2.降级规则

2.1 RT(平均响应时间)

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

后台加个/testC的方法,设置睡眠1秒,这样响应时间就超过阈值了

 @GetMapping("/testC")
    public String testC() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "------test降级RT";
    }

荐
                                                        SpringCloud Alibaba Sentinel(史上最详细)
用jmeter测试并发访问
荐
                                                        SpringCloud Alibaba Sentinel(史上最详细)
测试结论: 永远1秒钟打进来10个请求(大于5个请求了)去调用testC,并且平均响应时间大于200ms,则在未来的5s内,断路器打开,微服务不可用,停止jmeter,断路器关闭,微服务恢复正常

2.2 异常比例

异常比例: 当资源的每秒请求大于5,并且每秒异常总数占通过量的比值超过阈值之后,资源进入降级状态,在接下来的时间窗口内,对该方法的调用都会自动的返回。异常的比例在[0.1,1.0]
荐
                                                        SpringCloud Alibaba Sentinel(史上最详细)
将testC的方法制造一个运行异常

@GetMapping("/testC")
    public String testC() {
       int i = 10/0;
        return "------test降级异常比例";
    }

测试结论: 单独访问一次,必然页面会返回一个error page(运行异常),调用一次,错一次;开启jmeter,直接高并发请求,多次调用达到我们的配置条件,也就是超过了异常比例的阈值,断路器就开启了,微服务不能用,不在是报错页面了,而是服务降级
荐
                                                        SpringCloud Alibaba Sentinel(史上最详细)

2.3 异常数

异常数: 当资源近1分钟的异常数超过阈值之后会进行熔断。注意由于统计时间窗口是分钟级别的,若时间小于60s,则结束熔断状态后仍可能再进入熔断状态
荐
                                                        SpringCloud Alibaba Sentinel(史上最详细)
测试结论:在1分钟以内,点击3次/testC后,再次点击就会返回降级页面,之前3次返回的是错误页面,进入熔断,70s后,断路器关闭,微服务恢复

3.热点key规则

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

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

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

后端代码:

@GetMapping("/testHotKey")
    @SentinelResource(value = "testHotKey",blockHandler = "block_testHotKey")
    public String testHotKey(@RequestParam(value = "p1",required = false)String p1,
                             @RequestParam(value = "p2",required = false)String p2){
        return "testHotKey....";
    }
    public String block_testHotKey(String p1, String p2, BlockException exception){
        return "啊哦,testHotKey被限流了...";
    }
}
  • @SentinelResource注解和Hystrix中的@HystrixCommand类似,之前的案例,限流、降级出问题了,都是用的sentinel默认的提示信息,这个注解就是类似hystrix的注解,自定义兜底方法,某个方法出问题,就找对应的兜底方法
    value = “testHotKey”:就是该资源的唯一标识,blockHandler = “block_testHotKey”:就是兜底方法
  • @RequestParam(value = “p1”,required = false):springboot中的注解,对请求参数的设置,required = false设置参数为不必须,参数可有可无
  • block_testHotKey(String p1, String p2, BlockException exception):兜底方法要有原方法的参数,且含有BlockException

sentinel配置:
荐
                                                        SpringCloud Alibaba Sentinel(史上最详细)
测试结果:可以看到当我们访问/testHotKey的时候带上p1参数时,每秒超过1次,就会触发限流,并且走的是我们自定义的兜底方法,不是之前sentinel自带的
注: 带p1和p2也会触发限流,只带p2不会触发,所以只要参数含有p1就会触发限流
荐
                                                        SpringCloud Alibaba Sentinel(史上最详细)
添加参数例外项:
特殊情况:我们期望p1参数当它是某个特殊值时,它的限流值和平时不一样
荐
                                                        SpringCloud Alibaba Sentinel(史上最详细)

1.参数类型:参数的类型必须是基本类型和String
2.参数值:就是你需要配置的参数例外
3.限流阈值:参数例外项重新改为这个阈值

4.系统规则

系统保护规则是从应用级别的入口流量进行控制,从单台机器的 load、CPU 使用率、平均 RT、入口 QPS 和并发线程数等几个维度监控应用指标,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。
系统保护规则是应用整体维度的,而不是资源维度的,并且仅对入口流量生效。入口流量指的是进入应用的流量(EntryType.IN),比如 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让你们体会一下:
荐
                                                        SpringCloud Alibaba Sentinel(史上最详细)
测试效果:可以看到,配置了全局的入口QPS后,无论是testA,还是testB都是每秒1次,超过阈值就限流
荐
                                                        SpringCloud Alibaba Sentinel(史上最详细)

四.@SentinelResource注解的详细使用

1.按资源名称限流+后续处理

业务类controller:

@RestController
public class RateLimitController
{
    @GetMapping("/byResource")
    @SentinelResource(value = "byResource",blockHandler = "handleException")
    public CommonResult byResource()
    {
        return new CommonResult(200,"按资源名称限流测试OK",new Payment(2020L,"serial001"));
    }
    public CommonResult handleException(BlockException exception)
    {
        return new CommonResult(444,exception.getClass().getCanonicalName()+"\t 服务不可用");
    }

sentinel配置:
荐
                                                        SpringCloud Alibaba Sentinel(史上最详细)
测试结果:走的自定义的blockHandler
荐
                                                        SpringCloud Alibaba Sentinel(史上最详细)

2.按照Url地址限流+后续处理

通过访问的URL来限流,会返回Sentinel自带默认的限流处理信息
业务类controller:

 @GetMapping("/byUrl")
    @SentinelResource(value = "byUrl")
    public CommonResult byUrl() {
        return new CommonResult(200, "按url限流测试OK", new Payment(2020L, "serial002"));
    }

sentinel配置:
荐
                                                        SpringCloud Alibaba Sentinel(史上最详细)
测试结果:通过访问的URL来限流,会返回Sentinel自带默认的限流处理信息

3.客户自定义限流处理逻辑

上面兜底方法面临的问题?
1.系统默认的,没有体现我们自己的业务要求
2.依照现有条件,我们自定义的处理方法又和业务代码耦合在一起,不直观
3.每个业务代码都添加一个兜底的,那代码膨胀加剧
4.全局统一的处理方法没有体现
所以我们要自定义限流处理逻辑

创建customerBlockHandler类用于自定义限流处理逻辑:

public class CustomerBlockHandler {
    public static CommonResult handleException(BlockException exception) {
        return new CommonResult(444, exception.getClass().getCanonicalName() + "\t 服务不可用"+"handleException---1");
    }
    public static CommonResult handleException2(BlockException exception) {
        return new CommonResult(444, exception.getClass().getCanonicalName() + "\t 服务不可用"+"handleException---2");
    }
}

controller:

@GetMapping("/customerBlockHandler")
    @SentinelResource(value = "customerBlockHandler", //自定义只对资源名有效,url走的还是系统默认的
            blockHandlerClass = CustomerBlockHandler.class,
            blockHandler = "handleException2")
    public CommonResult customerBlockHandler()
    {
        return new CommonResult(200,"按客戶自定义",new Payment(2020L,"serial003"));
    }
  • 自定义只对资源名有效,url走的还是系统默认的
  • blockHandlerClass = CustomerBlockHandler.class,
    blockHandler = “handleException2”
    指定自定义的类和方法,就可以找到兜底方法

sentinel配置:
荐
                                                        SpringCloud Alibaba Sentinel(史上最详细)
测试结果:
荐
                                                        SpringCloud Alibaba Sentinel(史上最详细)

五.服务熔断功能

sentinel整合ribbon:

  • 先创建两个服务提供者9003、9004

pom.xml:

<dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <!--SpringCloud ailibaba nacos -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <dependency><!-- 引入自己定义的api通用包,可以使用Payment支付Entity -->
            <groupId>com.baidu</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>
        <!-- SpringBoot整合Web组件 -->
        <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>
        <!--日常通用jar包配置-->
        <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>

application.yml:

server:
  port: 9003

spring:
  application:
    name: nacos-payment-provider
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 #配置Nacos地址

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

主启动类:

@SpringBootApplication
@EnableDiscoveryClient
public class PaymentMain9003
{
    public static void main(String[] args) {
        SpringApplication.run(PaymentMain9003.class, args);
    }
}

业务类:

@RestController
public class PaymentController
{
    @Value("${server.port}")
    private String serverPort;

    public static HashMap<Long, Payment> hashMap = new HashMap<>();
    static{
        hashMap.put(1L,new Payment(1L,"28a8c1e3bc2742d8848569891fb42181"));
        hashMap.put(2L,new Payment(2L,"bba8c1e3bc2742d8848569891ac32182"));
        hashMap.put(3L,new Payment(3L,"6ua8c1e3bc2742d8848569891xt92183"));
    }

    @GetMapping(value = "/paymentSQL/{id}")
    public CommonResult<Payment> paymentSQL(@PathVariable("id") Long id){
        Payment payment = hashMap.get(id);
        CommonResult<Payment> result = new CommonResult(200,"from mysql,serverPort:  "+serverPort,payment);
        return result;
    }
}
  • 创建消费服务者84

pom.xml:

<dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>
        <dependency>
            <groupId>com.baidu</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </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>

application.yml:

server:
  port: 84
spring:
  application:
    name: nacos-order-consumer
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
    sentinel:
      transport:
        dashboard: localhost:8080
        port: 8719

service-url:
  nacos-user-service: http://nacos-payment-provider

#对Feign的支持
feign:
  sentinel:
    enabled: true

主启动类:

@EnableDiscoveryClient
@SpringBootApplication
@EnableFeignClients
public class OrderNacosMain84
{
    public static void main(String[] args) {
        SpringApplication.run(OrderNacosMain84.class, args);
    }
}

配置类:

@Configuration
public class ApplicationContextConfig
{
    @Bean
    @LoadBalanced
    public RestTemplate getRestTemplate()
    {
        return new RestTemplate();
    }
}

业务类controller:

@RestController
@Slf4j
public class CircleBreakerController {
    public static final String SERVICE_URL = "http://nacos-payment-provider";

    @Resource
    private PaymentService paymentService;

    @Resource
    private RestTemplate restTemplate;

    @GetMapping("/consumer/fallback/{id}")
    // @SentinelResource(value = "fallback",fallback = "handlerFallback")//fallback只负责业务异常
    // @SentinelResource(value = "fallback",blockHandler = "blockHandler")//blockHandler只负责sentinel配置出错
    @SentinelResource(value = "fallback",blockHandler = "blockHandler",fallback = "handlerFallback")//两个都配置,如果都出错,会进入blockHandler
    public CommonResult<Payment> fallback(@PathVariable("id")Long id){
        CommonResult<Payment> result = restTemplate.getForObject(SERVICE_URL + "/paymentSQL/" + id, CommonResult.class, id);
        if (id == 4) {
            throw new IllegalArgumentException ("IllegalArgumentException,非法参数异常....");
        }else if (result.getData() == null) {
            throw new NullPointerException ("NullPointerException,该ID没有对应记录,空指针异常");
        }
        return result;
    }
    //fallback = "handlerFallback"
    public CommonResult<Payment> handlerFallback(@PathVariable("id")Long id,Throwable e){
        Payment payment = new Payment(id,"");
        return new CommonResult<>(444,"运行异常,handlerFallback,exception内容:"+e.getMessage(),payment);
    }
    //blockHandler = "blockHandler"
    public CommonResult<Payment> blockHandler(@PathVariable("id")Long id, BlockException e){
        Payment payment = new Payment(id,"");
        return new CommonResult<>(455,"运行异常,blockHandler,BlockException:"+e.getMessage(),payment);
    }
}

fallback只负责业务异常
blockHandler只负责sentinel配置出错
两个都配置,如果都出错,会进入blockHandler

sentinel配置:
荐
                                                        SpringCloud Alibaba Sentinel(史上最详细)
测试效果:
可以看到,正常访问,会有负载均衡的效果,id=4、5时抛异常走的自定义的fallback方法,快速点击,走的是自定义的blockHandler方法
荐
                                                        SpringCloud Alibaba Sentinel(史上最详细)

六.Sentinel的规则持久化

前面所有讲解过程有个重要问题:
一旦我们重启应用,Sentinel规则将消失,生产环境需要将配置规则进行持久化!
怎么配置:
将限流配置规则持久化进Nacos保存,只要刷新8401某个rest地址,sentinel控制台的流控规则就能看到,只要Nacos里面的配置不删除,针对8401上Sentinel上的流控规则持续有效
配置8401:
pom.xml:

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

application.yml:

server:
  port: 8401

spring:
  application:
    name: cloudalibaba-sentinel-service
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 #Nacos服务注册中心地址
    sentinel:
      transport:
        dashboard: localhost:8080 #配置Sentinel dashboard地址
        port: 8719
      datasource:
        ds1:
          nacos:
            server-addr: localhost:8848
            dataId: cloudalibaba-sentinel-service
            groupId: DEFAULT_GROUP
            data-type: json
            rule-type: flow

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

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

添加Nacos业务规则配置
荐
                                                        SpringCloud Alibaba Sentinel(史上最详细)

[
    {
         "resource": "/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 Up,2代表排队等待
clusterMode:是否集群

经过上述配置,关闭8401服务,再重启,刷新sentinel,发现流控规则已经持久化!

至此,强大的SpringCloud Alibaba Sentinel就跟各位介绍完了,只是个人的一个学习笔记,记录一下分享给大家,有什么不对的地方,希望朋友们指出~~

本文地址:https://blog.csdn.net/weixin_44757206/article/details/107119085