SpringCloud-Sentinel的使用

Sentinel

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

(一)sentinel初始化监控

1.编码

1.下面是本项目需要用到的jar包(对于第一个板块,下面的sentinel-datasource-nacos和spring-cloud-starter-openfeign可以先不引入)

		<dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!--SpringCloud ailibaba sentinel-datasource-nacos 后续做持久化用到-->
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-datasource-nacos</artifactId>
        </dependency>
        <!--SpringCloud ailibaba 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>
        <!-- SpringBoot整合Web组件+actuator -->
        <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>

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:9090
        #默认8719端口,假如被占用会自动从8719开始依次+1扫描,直至找到未被占用的端口
        port: 8719


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

3.编写一个没什么特点的启动类
在这里插入图片描述
4.编写一个测试用的controller:

package org.lzl.springcloud.alibaba.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

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

2.运行

启动nocos,sentinel(端口为9090)和项目
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.测试

我们看到nocos中有此项目的名称
在这里插入图片描述
而sentinel的控制台却空空如也,其原因是因为sentinel默认是懒加载,只有有请求过来之后才有监控显示。
在这里插入图片描述
于是我们在浏览器中访问http://localhost:8401/testAhttp://localhost:8401/testB,再次查看sentinel的控制台发现已经有监控效果了!
在这里插入图片描述






(二)Sentinel流控规则

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

1.QPS直接失败

比如我想对 /testA 这个请求做限流控制
在这里插入图片描述
下面需要填写的的就是单机阈值这个框框,填1的意思是,1s中内请求次数超过1次就会限流
在这里插入图片描述
点击添加后,我们可以看到流控规则中有我们刚刚创建的规则
在这里插入图片描述

在浏览器中访问http://localhost:8401/testA,访问的频率低于1s1次就没什么影响,一旦频率过高就会看到下面的情况:
在这里插入图片描述

2.线程数的直接失败

原理: 当调用该api的线程数达到设定的阈值,进行限流
类似于在银行办业务,同一个窗口同一时间只有一个客户在办理,其他客户必须等该客户办理完之后才可以办理
下面是测试的接口:

    @GetMapping("/testB")
    public String testB(){
        try{ TimeUnit.MILLISECONDS.sleep(800); }catch (InterruptedException e){ e.printStackTrace(); }
        return "---------testB";
    }

我们给上面的接口定义一个流控规则:
在这里插入图片描述
然后两个客户端在很短的时间同时访问这个接口,就会出现下面的情况:
在这里插入图片描述
在这里插入图片描述

3.流控-关联

比如下面的两个接口,当与A关联的资源B达到阈值后,就限流A自己。

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

在这里插入图片描述
测试的时候需要用到postman工具,下面是配置postman使其并发访问/testB,首先我们要将该请求加入collection中
在这里插入图片描述
在这里插入图片描述
然后我们需要接着配置collection:
在这里插入图片描述
在这里插入图片描述
点击Run collection!,我们发现postman已经在不同的向/testB发送请求了
在这里插入图片描述
此时访问我们用浏览器访问/testA,发现已经限流了:
在这里插入图片描述

4.预热

Warm Up(ReleConstant.COUNTROL_BEHAVIOR_WARM_UP)方式,即预热/冷启动方式。当系统长期处于低水位的情况下,当流量突然增加时,直接把系统拉升到高水位可能瞬间把系统压垮。通过“冷启动”,让通过的流量缓慢增加,在一定时间内逐渐增加到阈值上限,给冷系统一个预热的时间,避免冷系统被压垮。
公式:阈值除以coldFactor(默认值为3),经过预热时长后才会达到阈值。
默认coldFactor为3,即请求QPS从threshold/3开始,经预热时长逐渐升至设定的QPS阈值。

在这里插入图片描述
上面设置的意思就是请求QPS一开始是10/3,经过5s后才达到10.

5.排队等候

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

访问的接口是下面这个:

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

在这里插入图片描述
我们快速在浏览器狂按f5访问/testA,可以在后台看到下面的信息:
在这里插入图片描述








(三)服务降级

Sentinel熔断降级会在调用链路中某个资源出现不稳定状态时(例如调用超时或异常比例升高),对这个资源的调用进行限制,让请求快速失败,避免影响到其他的资源而导致级联错误。当资源被降级后吗,在接下来的降级时间窗口之内,对该资源的调用都自动熔断(默认行为是抛出DegradeException),下面是降级的三个策略:

  • RT(平均响应时间,秒级)
    平均响应时间超出阈值在时间窗口内通过通过的请求>=5,两个条件同时满足后触发降级
    窗口期过后关闭断路器
    RT最大4900(更大的需要通过-Dcsp.sentinel.statistic.max.rt=XXX才能生效)
  • 异常比例(秒级)
    QPS>=5且异常比例(秒级统计)超过阈值时,触发降级;时间窗口结束后,关闭降级。
  • 异常数(分钟级)
    异常数(分钟统计)超过阈值时,触发降级;时间窗口结束后,关闭降级。

具体请看:https://github.com/alibaba/Sentinel/wiki/%E7%86%94%E6%96%AD%E9%99%8D%E7%BA%A7

1.RT

平均响应时间(DEGRADE_GRADE_RT):当1s内持续进入5个请求,对应时刻的平均响应时间(秒级)均超过阈值(count,以ms为单位),那么在接下来的时间窗口(DegradeRule中的timeWindow,以s为单位)之内,对这个方法的调用都会自动地熔断(抛出DegradeException)。注意Sentinel默认统计的RT上限是4900ms,超出此阈值的都会算作4900ms,若需要变更此上限可以通过启动配置项-Dcsp.sentinel.statistic.max.rt=XXX来配置

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

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
按照上述配置:永远一秒钟打进来10个线程(大于5个了)调用testD,我们希望200ms处理完本次任务,如果超过200ms还没处理完,在未来1s钟的时间窗口内,断路器打开(保险丝跳闸)微服务不可用,保险丝跳闸断电了!(所以用jmeter不断的每秒10个请求时,我们用浏览器访问可以看到下面服务降级的效果)
在这里插入图片描述

2.异常比例

异常比例(DEGRADE_GRADE_RATIO):当资源的每秒请求量>=5,并且每秒异常总数占通过量的比值超过阈值(DegradeRule中的count)之后,资源进入降级状态,即在接下来的时间窗口(DegradeRule中的timeWindow,以s为单位)之内,对这个方法的调用都会自动地返回。异常比率的阈值范围是[0.0,1.0],代表0%-100%

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

在这里插入图片描述
正常访问,我们是无法每秒访问5次的,所以我们可以看到下面的报错界面:
在这里插入图片描述
我们用jmeter进行测试:

在这里插入图片描述
这样操作就会导致每秒10个请求,且异常比例是1,这样就会导致服务降级,再次浏览器访问就会看到下面的结果:
在这里插入图片描述

3.异常数

异常数(DEGRADE_GRADE_EXCEPTION_COUNT):当资源近1分钟的异常数目超过阈值之后会进行熔断。注意由于统计时间窗口是分钟级别的,若timeWindow小于60s,则熔断状态后仍可能再进入熔断状态。

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

在这里插入图片描述
第一次访问绝对报错,因为除数不能为0,我们看到error窗口,但是达到5次报错之后,进入熔断后降级:
在这里插入图片描述








(四)热点Key

1.基础使用

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

    @GetMapping("/testHotKey")
    @SentinelResource(value = "testHotKey",blockHandler = "deal_testHotKey")//注意和上面value的区别是没有/
    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(╥﹏╥)o";//sentinel系统默认的提示都是,Block by sentinel(flow limiting)
    }

注意下面的资源名,应该填写的是@SentinelResource的value
在这里插入图片描述
配置完成后,我们快速访问http://localhost:8401/testHotKey?p1=1,就会看到下面的自定义兜底的提示在这里插入图片描述
而快速访问http://localhost:8401/testHotKey?p2=1,每次都是正常显示的:
在这里插入图片描述
假如我们吧上面的接口改成下面的这个,也就是没有指定兜底的容错方法:

    @GetMapping("/testHotKey")
    @SentinelResource(value = "testHotKey")//注意和上面value的区别是没有/
    public String testHotKey(@RequestParam(value = "p1",required = false) String p1,
                             @RequestParam(value = "p2",required = false) String p2){
        return "-------testHotKey";
    }

再次快速的访问http://localhost:8401/testHotKey?p1=1,我们发现页面报错:
在这里插入图片描述

2.进阶用法

我们期望参数等于某个特定的值时,他的限流值和平时不一样!比如下面的就是当第一个参数值为5时,每秒的QPS大于200才会限流。

在这里插入图片描述
我们狂刷http://localhost:8401/testHotKey?p1=5,结果都是正常的:
在这里插入图片描述
补充一个知识:假如我们手贱自己写一个异常:

    @GetMapping("/testHotKey")
    @SentinelResource(value = "testHotKey",blockHandler = "deal_testHotKey")//注意和上面value的区别是没有/
    public String testHotKey(@RequestParam(value = "p1",required = false) String p1,
                             @RequestParam(value = "p1",required = false) String p2){
        int age=10/0;
        return "-------testHotKey";
    }
    public String deal_testHotKey(String p1, String p2, BlockException exception){
        return "********deal_testHotKey,o(╥﹏╥)o";//sentinel系统默认的提示都是,Block by sentinel(flow limiting)
    }

我们访问这个接口时,错误并不会被deal_testHotKey兜底,blockHandler只处理Sentinel控制台配置的违规情况!
在这里插入图片描述








(五) 系统规则

系统保护规则是从应用级别的入口流量进行控制,从单台机器的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进行举例说明:
在这里插入图片描述
添加了上面的系统规则之后,某一秒访问项目所有路径的请求只要大于1次就会阻塞:
在这里插入图片描述
在这里插入图片描述








(六)@SentinelResource注解的使用

1.情况一

当Sentinel控制台对下面的@SentinelResource的value值进行流控,达到阈值就会被自定义的handleException捕获。

    @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 服务不可用");
    }

在这里插入图片描述
快速访问http://localhost:8401/byResource,就会出现下面的结果:
在这里插入图片描述

2.情况二

跟上面的区别是@SentinelResource中没有blockHandler 属性

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

在这里插入图片描述
这样快速的访问访问http://localhost:8401/rateLimit/byUrl会出现下面的结果:
在这里插入图片描述

3.情况三

如果一个方法就对应一个兜底,就会导致代码膨胀,解决方法,单独写一个兜底的类(其中有很多不同的兜底方法),在@SentinelResource中进行指定。

下面是兜底类:

public class CustomerBlockHandler
{
    //注意下面static关键字
    public static CommonResult handlerException(BlockException exception)
    {
        return new CommonResult(4444,"按客戶自定义,global handlerException----1");
    }
    public static CommonResult handlerException2(BlockException exception)
    {
        return new CommonResult(4444,"按客戶自定义,global handlerException----2");
    }
}

测试时controller的接口:

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

在这里插入图片描述
添加上面的流控规则之后,快速访问http://localhost:8401/rateLimit/customerBlockHandler,就会被自定义的兜底类兜底:
在这里插入图片描述





(七) Sentinel服务熔断

直接用小案例来说明sentinel的相关配置:

1.服务端

1.pom.xml需要的依赖如下:

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <dependency><!-- 引入自己定义的api通用包,可以使用Payment支付Entity -->
            <groupId>org.lzl</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>

2.application.yml的配置

server:
  port: 9003

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

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

3.写一个普通的启动类:
在这里插入图片描述
4.写一个controller,供客户端调用:

    @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;
    }

5.仿照上面的配置,再创造一个端口为9004的服务端

2.客户端(使用restTemplate)

1.引入下面的依赖

	<!--SpringCloud ailibaba nacos -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!--SpringCloud ailibaba sentinel -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>
        <!-- 引入自己定义的api通用包,可以使用Payment支付Entity -->
        <dependency>
            <groupId>org.lzl</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>

2.编写下面的application.yml

server:
  port: 84


spring:
  application:
    name: nacos-order-consumer
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
    sentinel:
      transport:
        #配置Sentinel dashboard地址
        dashboard: localhost:9090
        #默认8719端口,假如被占用会自动从8719开始依次+1扫描,直至找到未被占用的端口
        port: 8719

#消费者将要去访问的微服务名称(注册成功进nacos的微服务提供者)
service-url:
  nacos-user-service: http://nacos-payment-provider

3.编写一个普通的启动类:
在这里插入图片描述
4.加入下面的bean

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

5.写下面的controller,用来进行远程调用:

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

    @Resource
    private RestTemplate restTemplate;

    @RequestMapping("/consumer/fallback/{id}")
    @SentinelResource(value = "fallback") //没有配置  1号注释
    //@SentinelResource(value = "fallback",fallback = "handlerFallback") //fallback只负责业务异常 2号注释
    //@SentinelResource(value = "fallback",blockHandler = "blockHandler") //blockHandler只负责sentinel控制台配置违规    3号注释
/*    @SentinelResource(value = "fallback",fallback = "handlerFallback",blockHandler = "blockHandler",
            exceptionsToIgnore = {IllegalArgumentException.class})  4号注释*/
    public CommonResult<Payment> fallback(@PathVariable 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
    public CommonResult handlerFallback(@PathVariable  Long id,Throwable e) {
        Payment payment = new Payment(id,"null");
        return new CommonResult<>(444,"兜底异常handlerFallback,exception内容  "+e.getMessage(),payment);
    }
    //本例是blockHandler
    public CommonResult blockHandler(@PathVariable  Long id,BlockException blockException) {
        Payment payment = new Payment(id,"null");
        return new CommonResult<>(445,"blockHandler-sentinel限流,无此流水: blockException  "+blockException.getMessage(),payment);
    }
}

6.开启下面的限流规则
在这里插入图片描述

测试

1.如果用的是注释1,@SentinelResource(value = "fallback")
快速访问时,请求被限流就会报下面的错误页面。
在这里插入图片描述
如果是本身的运行时runtime异常就会报下面的错误页面
在这里插入图片描述

2.如果使用的是注释2,@SentinelResource(value = "fallback",fallback = "handlerFallback"),他就会只处理java的运行时异常,而不管sentinel控制台的限流异常。
抛出运行时异常时,自动的被fallback指定的方法兜底:

在这里插入图片描述
而发生sentinel的限流异常时,其实也会被fallback指定的方法兜底,只是异常信息打不出来,所以建议最好别用fallback来处理sentinel的流控规则。
在这里插入图片描述
3.如果使用的是注释3,@SentinelResource(value = "fallback",blockHandler = "blockHandler"),他就只管Sentinel控制台设置的流控,而不管java的运行时异常。
我们快速访问接口,使其达到限流,发现限流异常会被指定的blockHandler兜底:
在这里插入图片描述
而java的运行时异常依旧是错误的界面:
在这里插入图片描述
4.如果使用的注解4,则就两种异常都支持,出了事各回各家,各找各妈,如果指定了exceptionsToIgnore这个参数,意思就是不处理指定的异常。

3.客户端(使用Openfeign)

1.在上面客户端的基础上添加下面的依赖:

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

2.在上面客户端的基础上给application.yml添加下面的内容

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

3.主启动上添加该注解
在这里插入图片描述
3.编写下面的service接口,用于远程调用,并在@FeignClient中指定fallback的兜底类

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

4.编写service的实现类(用于兜底)

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

5.编写下面的controller:

    @Resource
    private PaymentService paymentService;

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

测试

我们访问http://localhost:84/consumer/paymentSQL/1,发现一切都是正常的
在这里插入图片描述
然而我们现在立刻去关掉服务端的进程,再去访问http://localhost:84/consumer/paymentSQL/1,就会看到下面的结果:
在这里插入图片描述






(八)Sentinel持久化

1.引入下面的依赖:

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

2.修改application.yml的配置:(看!!!!!的地方)

server:
  port: 8401

spring:
  application:
    name: cloudalibaba-sentinel-service
  cloud:
    nacos:
      discovery:
        #Nacos服务注册中心地址
        server-addr: localhost:8848
    sentinel:
      transport:
        #配置Sentinel dashboard 地址
        dashboard: localhost:9090
        #默认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  #!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
management:
  endpoints:
    web:
      exposure:
        include: '*'

3.nacos中添加下面的规则:

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

4.我们启动该项目,发现sentinel已经对这个流控持久化了:
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

键盘歌唱家

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

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

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

打赏作者

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

抵扣说明:

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

余额充值