1、SpringCloud Alibaba Sentinel实现熔断与限流

1、Sentinel

1、官网

https://github.com/alibaba/Sentinel
中文:https://github.com/alibaba/Sentinel/wiki/%E4%BB%8B%E7%BB%8D

2、是什么

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

3、下载

https://github.com/alibaba/Sentinel/releases

4、作用

image.png

5、怎么玩

https://spring-cloud-alibaba-group.github.io/github-pages/greenwich/spring-cloud-alibaba.html#_spring_cloud_alibaba_sentinel

  • 服务使用中的各种问题

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

      2、安装Sentinel控制台

      1、sentinel组件由2部分组成

  • 核心库(Java 客户端)不依赖任何框架/库,能够运行于所有 Java 运行时环境,同时对 Dubbo / Spring Cloud 等框架也有较好的支持。

    • 后台
  • 控制台(Dashboard)基于 Spring Boot 开发,打包后可以直接运行,不需要额外的 Tomcat 等应用容器。

  • v1.8.2

    2、运行命令

  • 前提

    • java8环境OK
    • 8080端口不能被占用
  • 命令

    1. java -jar sentinel-dashboard-1.7.0.jar

    3、访问sentinel管理界面

  • http://localhost:8080

  • 账号密码都是sentinel

    3、初始化演示工程

    1、启动相关服务

  • nacos

访问http://localhost:8848/nacos/#/login

  • 启动sentinel

    java -jar sentinel-dashboard-1.7.0.jar
    

    2、创建工程cloudalibaba-sentinel-service8401

    1、修改pom

    ```xml <?xml version=”1.0” encoding=”UTF-8”?> <project xmlns=”http://maven.apache.org/POM/4.0.0

       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    

      <artifactId>cloud2020</artifactId>
      <groupId>com.daijunyi</groupId>
      <version>1.0-SNAPSHOT</version>
    

    4.0.0 cloudalibaba-sentinel-service8401 com.daijunyi cloud-api-commons ${project.version} com.alibaba.cloud spring-cloud-starter-alibaba-nacos-discovery com.alibaba.csp sentinel-datasource-nacos com.alibaba.cloud spring-cloud-starter-alibaba-sentinel org.springframework.cloud spring-cloud-starter-openfeign org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-actuator org.springframework.boot spring-boot-devtools runtime true cn.hutool hutool-all 4.6.3 org.projectlombok lombok true org.springframework.boot spring-boot-starter-test test

<a name="bomNJ"></a>
#### 2、修改yaml
```yaml
server:
  port: 8401

spring:
  application:
    name: cloudalibaba-sentinel-service
  cloud:
    nacos:
      discovery:
        server-addr: localhost:1111
    sentinel:
      transport:
        dashboard: localhost:8080
        port: 8719  #默认8719,假如被占用了会自动从8719开始依次+1扫描。直至找到未被占用的端口

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

3、主启动类

package com.daijunyi;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableDiscoveryClient
public class SentinelService8401 {

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

4、业务类

  • controller ```java package com.daijunyi.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";
}

}

<a name="M4RVy"></a>
#### 5、查看nacos注册的服务
![image.png](https://cdn.nlark.com/yuque/0/2021/png/12971636/1631159112621-767ce86a-3fda-4cef-968b-ef115eedb857.png#clientId=u48bb990c-06f3-4&from=paste&height=395&id=u10837d97&margin=%5Bobject%20Object%5D&name=image.png&originHeight=790&originWidth=2868&originalType=binary&ratio=1&size=142689&status=done&style=none&taskId=udbe37cd0-d292-42da-aade-944e5e4f740&width=1434)
<a name="Zozda"></a>
### 3、启动8401微服务后查看sentienl控制台

- 访问[http://localhost:8080](http://localhost:8080/#/dashboard/home)
   - ![image.png](https://cdn.nlark.com/yuque/0/2021/png/12971636/1631159241802-f955afc7-05f8-47a1-8df2-faae5a1997ba.png#clientId=u48bb990c-06f3-4&from=paste&height=399&id=u733ef825&margin=%5Bobject%20Object%5D&name=image.png&originHeight=798&originWidth=2878&originalType=binary&ratio=1&size=106616&status=done&style=none&taskId=u353a515e-6f11-4c30-ae0a-b6e7ae9e658&width=1439)
- Sentinel采用的懒加载说明
   - 执行一次访问即可
      - [http://localhost:8401/testA](http://localhost:8401/testA)
      - [http://localhost:8401/testB](http://localhost:8401/testB)
   - 查看效果
      - ![image.png](https://cdn.nlark.com/yuque/0/2021/png/12971636/1631159330101-36ca294f-de93-4605-8e77-a5251b2e4e99.png#clientId=u48bb990c-06f3-4&from=paste&height=675&id=u5572c12f&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1350&originWidth=2820&originalType=binary&ratio=1&size=247087&status=done&style=none&taskId=ua188b6d2-d290-43db-93e1-42771caf551&width=1410)
   - sentinel8080正在监控微服务8401
<a name="aiL1O"></a>
## 4、流控规则
<a name="rp4AK"></a>
### 1、基本介绍
![image.png](https://cdn.nlark.com/yuque/0/2021/png/12971636/1631159418037-12119ea1-ceaa-4e9e-9500-50b5f6690cf9.png#clientId=u48bb990c-06f3-4&from=paste&height=649&id=u0222c00e&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1298&originWidth=2840&originalType=binary&ratio=1&size=277810&status=done&style=none&taskId=u1762797b-2c85-4a31-8da9-43e09490402&width=1420)

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

- 直接->快速失败
   - 系统默认
- 配置及说明
   - ![image.png](https://cdn.nlark.com/yuque/0/2021/png/12971636/1631160632416-8957a369-64e9-4e2c-9ad6-3ce375482c73.png#clientId=u48bb990c-06f3-4&from=paste&height=512&id=u424e932d&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1024&originWidth=1382&originalType=binary&ratio=1&size=104671&status=done&style=none&taskId=u499b68f4-8e24-4932-8d48-bccc584624a&width=691)
- 测试
   - 快速访问[http://localhost:8401/testA](http://localhost:8401/testA)
      - ![image.png](https://cdn.nlark.com/yuque/0/2021/png/12971636/1631160747334-0b738def-bdda-48cb-b0a3-4d19e53f77a1.png#clientId=u48bb990c-06f3-4&from=paste&height=68&id=u51979825&margin=%5Bobject%20Object%5D&name=image.png&originHeight=136&originWidth=636&originalType=binary&ratio=1&size=14373&status=done&style=none&taskId=u17ed47e2-02ef-47ff-98b5-11b4f6ddafb&width=318)
   - 问题
      - 直接调用默认报错信息,技术方面OK but,是否应该有我们自己的后续处理?
      - 应该类似有一个fallback的兜底方法?    
<a name="tgQtQ"></a>
#### 2、关联

- 是什么?
   - 当关联的资源达到阈值时,就限流自己
   - 当与A关联的资源B达到阈值后,就限流自己
   - B惹事,A挂了
- 配置说明
   - ![image.png](https://cdn.nlark.com/yuque/0/2021/png/12971636/1631160896259-11ca6582-604e-4401-81b7-7de20156f285.png#clientId=u48bb990c-06f3-4&from=paste&height=530&id=u66cdd1d4&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1060&originWidth=1326&originalType=binary&ratio=1&size=105177&status=done&style=none&taskId=u020727be-4a82-4243-b327-2b0f7c8e184&width=663)
- 测试
   - 运行postman访问/testB
      - 执行20次,每次请求之间间隔0.3秒
      - ![image.png](https://cdn.nlark.com/yuque/0/2021/png/12971636/1631162193127-e871e541-fdc5-4c09-8fc5-14ba6a62f687.png#clientId=u48bb990c-06f3-4&from=paste&height=729&id=ue9c49419&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1458&originWidth=998&originalType=binary&ratio=1&size=87179&status=done&style=none&taskId=uae13ae20-977d-4741-b3f8-87cacb27182&width=499)
   - 执行上的请求,请求[http://localhost:8401/testA](http://localhost:8401/testA)
      - ![image.png](https://cdn.nlark.com/yuque/0/2021/png/12971636/1631162233656-9ec7a363-d9c0-447a-bf34-813a634aa7fc.png#clientId=u48bb990c-06f3-4&from=paste&height=59&id=ua27659eb&margin=%5Bobject%20Object%5D&name=image.png&originHeight=118&originWidth=648&originalType=binary&ratio=1&size=14666&status=done&style=none&taskId=u1bee301f-ff77-4a1c-8ab4-68f87a99dc7&width=324)
   - 但是当/testB请求完毕之后再请求[http://localhost:8401/testA](http://localhost:8401/testA)
      - ![image.png](https://cdn.nlark.com/yuque/0/2021/png/12971636/1631162270404-9abbef85-da42-4ff4-af5e-05b5f0013876.png#clientId=u48bb990c-06f3-4&from=paste&height=70&id=uc65d0399&margin=%5Bobject%20Object%5D&name=image.png&originHeight=140&originWidth=670&originalType=binary&ratio=1&size=10912&status=done&style=none&taskId=u1f8f4734-7e2b-49a1-89c5-120492037e4&width=335)
<a name="yuGxi"></a>
#### 3、链路

- 链路就是,当我们一个请求A和B过来,然后都去调用地下的service层同一个方法C,使用注解@SentinelResource标志为资源名称”c“
   - 这个时候调用就会形成A-c,和B-c的一个链路,我们可以对资源c进行限流,但是只有当是从入口A过来的时候,我们才限流,B过来的请求访问资源c不限流,这个就是链路模式
- 坑:
   - 从1.6.3 版本开始,Sentinel Web filter默认收敛所有URL的入口context,因此链路限流不生效。
   - 1.7.0 版本开始(对应SCA的2.1.1.RELEASE),官方在CommonFilter 引入了WEB_CONTEXT_UNIFY 参数,用于控制是否收敛context。将其配置为 false 即可根据不同的URL 进行链路限流。
   - SCA 2.1.1.RELEASE之后的版本,可以通过配置spring.cloud.sentinel.web-context-unify=false即可关闭收敛,我们当前使用的版本是SpringCloud Alibaba 2.1.0.RELEASE,无法实现链路限流。所以我们至少使用2.1.1.RELEASE的版本,需要写代码的形式实现进行配置这个环境。
   - 修改父类pom中的SpringCloud Alibaba版本
```xml
<dependency>
  <groupId>com.alibaba.cloud</groupId>
  <artifactId>spring-cloud-alibaba-dependencies</artifactId>
  <version>2.1.1.RELEASE</version>
  <type>pom</type>
  <scope>import</scope>
</dependency>
  • 修改8401的yaml

    spring:
    cloud:
    sentinel:
     filter:
       enabled: false
    
  • 再自己写配置类 ```java package com.daijunyi.config;

import com.alibaba.csp.sentinel.adapter.servlet.CommonFilter; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;

@Configuration public class FilterContextConfig { @Bean public FilterRegistrationBean sentinelFilterRegistration() { FilterRegistrationBean registration = new FilterRegistrationBean(); registration.setFilter(new CommonFilter()); registration.addUrlPatterns(“/*”); // 入口资源关闭聚合 registration.addInitParameter(CommonFilter.WEB_CONTEXT_UNIFY, “false”); registration.setName(“sentinelFilter”); registration.setOrder(1); return registration; } }


- 业务代码修改
   - 增加service
```java
package com.daijunyi.service;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import org.springframework.stereotype.Service;

@Service
public class FlowLimitService {

    @SentinelResource(value = "flowLimit")
    public String flowLimit(){
        return "flowLimit";
    }
}
  • 修改controller
    • testA和testB都去调用flowLimit ```java package com.daijunyi.controller;

import com.alibaba.csp.sentinel.context.ContextUtil; import com.daijunyi.service.FlowLimitService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController;

@RestController public class FlowLimitController {

@Autowired
FlowLimitService flowLimitService;

@GetMapping("/testA")
public String testA() {
    String s = flowLimitService.flowLimit();
    return "------testA";
}

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

@GetMapping("/testC")
public String testC(){
    String s = flowLimitService.flowLimit();
    System.out.println(s);
    return "------testC";
}

}


- sentinel控制台配置
   - 对资源flowLimit进行限制
   - 并且是入口/testC来的
   - ![image.png](https://cdn.nlark.com/yuque/0/2021/png/12971636/1631167210156-342b0cb8-d7a8-421d-b658-3153fbd65fad.png#clientId=u48bb990c-06f3-4&from=paste&height=587&id=ub6924def&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1174&originWidth=2168&originalType=binary&ratio=1&size=209791&status=done&style=none&taskId=uf0db0141-b7c1-4f58-b258-0aee1259d27&width=1084)
- 测试
   - 快速访问[http://localhost:8401/testC](http://localhost:8401/testC)
      - ![image.png](https://cdn.nlark.com/yuque/0/2021/png/12971636/1631167264752-c56706d9-78eb-43c3-bce4-4b950869d971.png#clientId=u48bb990c-06f3-4&from=paste&height=344&id=uaca50850&margin=%5Bobject%20Object%5D&name=image.png&originHeight=688&originWidth=1482&originalType=binary&ratio=1&size=165989&status=done&style=none&taskId=ub977e6bf-3490-4b96-9822-c3e4d41a188&width=741)
   - 快速访问[http://localhost:8401/testA](http://localhost:8401/testA)
      - ![image.png](https://cdn.nlark.com/yuque/0/2021/png/12971636/1631167290509-cebf85ed-5c4d-4793-a8b2-d86f7915cec3.png#clientId=u48bb990c-06f3-4&from=paste&height=55&id=ucc7df9ea&margin=%5Bobject%20Object%5D&name=image.png&originHeight=110&originWidth=682&originalType=binary&ratio=1&size=10882&status=done&style=none&taskId=u854d844c-91fb-4d05-b305-950680fd806&width=341)
      - 不限制
<a name="ttBik"></a>
### 3、流控效果
<a name="QilPl"></a>
#### 1、直接->快速失败(默认的流控处理)

- 直接失败,抛出异常
   - Blocked by Sentinel (flow limiting)
- 源码
   - com.alibaba.csp.sentinel.slots.block.flow.controller.DefaultController
<a name="ZsnGd"></a>
#### 2、预热
<a name="kbFMd"></a>
##### 1、说明
公式:阈值除以coldFactor(默认值为3),经过预热时长后才会达到阈值
<a name="ThSou"></a>
##### 2、官网
[https://github.com/alibaba/Sentinel/wiki/%E9%99%90%E6%B5%81---%E5%86%B7%E5%90%AF%E5%8A%A8](https://github.com/alibaba/Sentinel/wiki/%E9%99%90%E6%B5%81---%E5%86%B7%E5%90%AF%E5%8A%A8)<br />当流量突然增大的时候,我们常常会希望系统从空闲状态到繁忙状态的切换的时间长一些。即如果系统在此之前长期处于空闲的状态,我们希望处理请求的数量是缓步的增多,经过预期的时间以后,到达系统处理请求个数的最大值。Warm Up(冷启动,预热)模式就是为了实现这个目的的。<br />这个场景主要用于启动需要额外开销的场景,例如建立数据库连接等。<br />它的实现是在 [Guava](https://github.com/google/guava/blob/master/guava/src/com/google/common/util/concurrent/SmoothRateLimiter.java) 的算法的基础上实现的。然而,和 Guava 的场景不同,Guava 的场景主要用于调节请求的间隔,即 [Leaky Bucket](https://en.wikipedia.org/wiki/Leaky_bucket),而 Sentinel 则主要用于控制每秒的 QPS,即我们满足每秒通过的 QPS 即可,我们不需要关注每个请求的间隔,换言之,我们更像一个 [Token Bucket](https://en.wikipedia.org/wiki/Token_bucket)。<br />我们用桶里剩余的令牌来量化系统的使用率。假设系统每秒的处理能力为 b,系统每处理一个请求,就从桶中取走一个令牌;每秒这个令牌桶会自动掉落b个令牌。令牌桶越满,则说明系统的利用率越低;当令牌桶里的令牌高于某个阈值之后,我们称之为令牌桶"饱和"。<br />当令牌桶饱和的时候,基于 Guava 的计算上,我们可以推出下面两个公式:<br />rate(c)=m*c+ coldrate <br />其中,rate 为当前请求和上一个请求的间隔时间,而 rate 是和令牌桶中的高于阈值的令牌数量成线形关系的。cold rate 则为当桶满的时候,请求和请求的最大间隔。通常是 coldFactor * rate(stable)。<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/12971636/1631167574265-e2e12a60-3307-41db-bcf9-0bcc6416bc91.png#clientId=u48bb990c-06f3-4&from=paste&height=516&id=uf359a4a9&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1032&originWidth=1168&originalType=binary&ratio=1&size=350249&status=done&style=none&taskId=u8550400b-24eb-4ba7-a60c-e7f44caa6fa&width=584)<br />默认coldFactor为3,即请求QPS从threshold/3开始,经预热时长逐渐升至设定的QPS阈值。
<a name="BLj31"></a>
##### 3、源码
com.alibaba.csp.sentinel.slots.block.flow.controller.WarmUpController<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/12971636/1631167703700-ae64a69f-6120-4023-af3c-c5f58a1f290d.png#clientId=u48bb990c-06f3-4&from=paste&height=382&id=ub60c5003&margin=%5Bobject%20Object%5D&name=image.png&originHeight=764&originWidth=1610&originalType=binary&ratio=1&size=136882&status=done&style=none&taskId=u44963ae5-2bce-415b-97bd-09b8f024273&width=805)
<a name="KlcAo"></a>
##### 4、配置
![image.png](https://cdn.nlark.com/yuque/0/2021/png/12971636/1631167786008-01747ff6-067e-4391-ad96-c7d853b24106.png#clientId=u48bb990c-06f3-4&from=paste&height=532&id=u82a1a212&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1064&originWidth=1372&originalType=binary&ratio=1&size=107863&status=done&style=none&taskId=uffddbc92-3183-4d9b-b981-31f153b91d1&width=686)
<a name="qUDUd"></a>
##### 5、测试

- 快速点击[http://localhost:8401/testB](http://localhost:8401/testB)
   - 发现刚开始总是出现被限流,慢慢的就不再限流了。可以抗住了
<a name="xCDHE"></a>
##### 6、应用场景
如:秒杀系统在开启的瞬间,会有很多流量上来,很有可能把系统打死,预热方式就是把为了保护系统,可慢慢的把流量放进来,慢慢的把阀值增长到设置的阀值
<a name="Wspww"></a>
#### 3、排队等待
<a name="PUaIn"></a>
##### 1、原理

- 匀速排队,阈值必须设置为QPS
- 匀速排队(RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER)方式会严格控制请求通过的间隔时间,也即是让请求以均匀的速度通过,对应的是漏桶算法。详细文档可以参考 [流量控制 - 匀速器模式](https://github.com/alibaba/Sentinel/wiki/%E6%B5%81%E9%87%8F%E6%8E%A7%E5%88%B6-%E5%8C%80%E9%80%9F%E6%8E%92%E9%98%9F%E6%A8%A1%E5%BC%8F),具体的例子可以参见 [PaceFlowDemo](https://github.com/alibaba/Sentinel/blob/master/sentinel-demo/sentinel-demo-basic/src/main/java/com/alibaba/csp/sentinel/demo/flow/PaceFlowDemo.java)。
- ![image.png](https://cdn.nlark.com/yuque/0/2021/png/12971636/1631168010262-91f694ee-989c-43d1-ac3e-f116838d322d.png#clientId=u48bb990c-06f3-4&from=paste&height=279&id=u14be3e47&margin=%5Bobject%20Object%5D&name=image.png&originHeight=558&originWidth=1632&originalType=binary&ratio=1&size=117453&status=done&style=none&taskId=u1e06f499-3073-444c-a7d0-36993b3c169&width=816)
- 这种方式主要用于处理间隔性突发的流量,例如消息队列。想象一下这样的场景,在某一秒有大量的请求到来,而接下来的几秒则处于空闲状态,我们希望系统能够在接下来的空闲期间逐渐处理这些请求,而不是在第一秒直接拒绝多余的请求。
- 注意:匀速排队模式暂时不支持 QPS > 1000 的场景
<a name="e4KNU"></a>
##### 2、源码
com.alibaba.csp.sentinel.slots.block.flow.controller.RateLimiterController
<a name="fs1tk"></a>
##### 3、配置

- 每秒只能一个
- 超时设置20秒

![image.png](https://cdn.nlark.com/yuque/0/2021/png/12971636/1631168177420-adaad4bd-0b99-478c-ae38-ea6a207d93a5.png#clientId=u48bb990c-06f3-4&from=paste&height=541&id=u59a41c4d&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1082&originWidth=1354&originalType=binary&ratio=1&size=101060&status=done&style=none&taskId=u1becbca2-afaf-46ed-916a-a5aa5bf6adb&width=677)

- 测试结果就是发现不过来多少请求,都是1秒处理一个请求。
<a name="cE4B1"></a>
## 5、降级规则
<a name="YGHoP"></a>
### 1、基本介绍

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

![image.png](https://cdn.nlark.com/yuque/0/2021/png/12971636/1631169172640-176d127d-a4c9-45a5-8419-9725ba37c88d.png#clientId=u48bb990c-06f3-4&from=paste&height=313&id=u4648f07f&margin=%5Bobject%20Object%5D&name=image.png&originHeight=626&originWidth=1356&originalType=binary&ratio=1&size=55158&status=done&style=none&taskId=udcbb30ed-ba90-4a54-853a-9e1c3ec4bba&width=678)

- Sentinel熔断降级会在调用链路中某个资源出现不稳定状态时(例如调用超时或异常比例升高),对这个资源的调用进行限制,让请求快速失败,避免影响到其它的资源而导致级联错误。当资源被降级后,在接下来的降级时间窗口之内,对该资源的调用都自动熔断(默认行为是抛出DegradeException) 。
- Sentinel的断路器是没有半开状态的
   - 半开的状态系统自动去检测是否请求有异常,没有异常就关闭断路器恢复使用,有异常则继续打开断路器不可用。具体可以参考Hystrix
   - ![image.png](https://cdn.nlark.com/yuque/0/2021/png/12971636/1631169406098-a5c1f6be-388b-417e-ad90-8e1bb295bdda.png#clientId=u48bb990c-06f3-4&from=paste&height=371&id=ubb3d9509&margin=%5Bobject%20Object%5D&name=image.png&originHeight=742&originWidth=1202&originalType=binary&ratio=1&size=110403&status=done&style=none&taskId=u890184a7-3132-405a-8c2d-cfe1d6ecf04&width=601)
<a name="EdCpb"></a>
### 2、降级策略实战
<a name="QusWm"></a>
#### 1、RT
<a name="pbqtX"></a>
##### 1、是什么
![image.png](https://cdn.nlark.com/yuque/0/2021/png/12971636/1631169470493-cd484bb1-f5d8-46a3-9db3-fe0ff6f7629b.png#clientId=u48bb990c-06f3-4&from=paste&height=617&id=u848dd453&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1234&originWidth=1412&originalType=binary&ratio=1&size=907014&status=done&style=none&taskId=uc5e130a1-f96c-477b-b6a2-9379271dbbc&width=706)
<a name="mXn6l"></a>
##### 2、测试

- 添加业务代码
```java
    @GetMapping("/testD")
    public String testD()
    {
        try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }
        log.info("testD 测试RT");

        return "------testD";
    }
  • 配置
    • image.png
  • jmeter压测
    • 发送20个线程,重复20000次
    • image.png
  • 并发请求大于5,并且每个请求的处理时间大于200毫秒,会导致服务熔断
  • 访问请求http://localhost:8401/testD

    • image.png

      2、异常比例

      1、是什么
      image.png
      2、测试
  • 修改代码

      @GetMapping("/testE")
      public String testE()
      {
    
          log.info("testD 测试RT");
          int age = 10/0;
          return "------testE";
      }
    
  • 配置

    • image.png
  • jmeter测试 发送20个并发线程请求
  • 访问http://localhost:8401/testE
    • image.png
  • image.png

    3、异常数

    1、是什么
  • 异常数是按照分钟统计的

image.png

2、测试
  • 配置
    • image.png
  • 发送请求http://localhost:8401/testE

  • @SentinelResource

  • 兜底方法
    • 分为系统默认和客户自定义,两种
    • 之前的case,限流出问题后,都是用sentine|系统默认的提示: Blocked by Sentinel (flow limiting)
    • 我们能不能自定?类似hystrix,某个方法出问题了,就找对应的兜底降级方法?
  • 结论

    • 从HystrixCommand到@SentinelResource

      4、代码

      @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) {
         //int age = 10/0;
         return "------testHotKey";
      }
      
      //兜底方法 
      public String deal_testHotKey (String p1, String p2, BlockException exception){
         return "------deal_testHotKey,o(╥﹏╥)o";
      }
      

      4、配置

  • 要对sentinelResource中的value进行配置

image.png

image.png

2、测试

  • 快速访问http://localhost:8401/testHotKey?p1=5
    • 当p1等于5的时候,阈值变为200
    • image.png
  • 快速访问http://localhost:8401/testHotKey?p1=3

    • 当p1不等于5的时候,阈值就是平常的1
    • image.png

      7、@SentinelResource中的blockHandler和fallback区别

  • blockHandler是对sentinel控制台的规则进行兜底控制

  • fallback是对java运行期的运行时异常进行兜底

    7、系统规则

    1、是什么

    image.png
    https://github.com/alibaba/Sentinel/wiki/%E7%B3%BB%E7%BB%9F%E8%87%AA%E9%80%82%E5%BA%94%E9%99%90%E6%B5%81

    2、各项配置参数说明

    系统保护规则是从应用级别的入口流量进行控制,从单台机器的 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 达到阈值即触发系统保护。

    3、测试一个QPS

  • 配置

    • image.png
  • 快速访问http://localhost:8401/testA
    • image.png
  • 快速访问http://localhost:8401/testB

    • image.png

      8、@SentinelResource

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

  • 启动Nacos成功

  • 启动Sentinel成功
  • 修改model cloudalibaba-sentinel-service8401
    • 添加业务类controller ```java package com.daijunyi.controller;

import com.alibaba.csp.sentinel.annotation.SentinelResource; import com.alibaba.csp.sentinel.slots.block.BlockException; import com.daijunyi.entities.CommonResult; import com.daijunyi.entities.Payment; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController;

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


- 配置流控规则
   - 表示1秒钟内查询次数大于1,就跑到我们自定义的处流,限流
   - ![image.png](https://cdn.nlark.com/yuque/0/2021/png/12971636/1631176433604-7e39ab0b-e9a6-4283-98aa-47466afcddbd.png#clientId=ubabf230a-8a0d-4&from=paste&height=405&id=u6b9756f2&margin=%5Bobject%20Object%5D&name=image.png&originHeight=810&originWidth=1378&originalType=binary&ratio=1&size=78486&status=done&style=none&taskId=u1cf9322a-0ffb-4de2-9475-f1bf3daee2d&width=689)
- 测试快速访问[http://localhost:8401/byResource](http://localhost:8401/byResource)
   - ![image.png](https://cdn.nlark.com/yuque/0/2021/png/12971636/1631176480127-f345a5a9-eaf9-4891-ba01-e6702565aabc.png#clientId=ubabf230a-8a0d-4&from=paste&height=74&id=uba8774f1&margin=%5Bobject%20Object%5D&name=image.png&originHeight=148&originWidth=1662&originalType=binary&ratio=1&size=30098&status=done&style=none&taskId=ubc9b819c-c616-4faa-b938-cafb34a94c2&width=831)
- 问题
   - 此时关闭微服务8401看看
   - Sentinel控制台,流控规则消失了?????
      - 临时/持久?
      - 临时的
<a name="SOdmC"></a>
### 2、客户自定义限流处理逻辑

- 创建customerBlockHandler类用于自定义限流处理逻辑
   - 注意一定要静态代码
```java
package com.daijunyi.handler;

import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.daijunyi.entities.CommonResult;

public class CustomerBlockHandler {

    public static CommonResult handleException(BlockException exception)
    {
        return new CommonResult(444,exception.getClass().getCanonicalName()+"\t 服务不可用");
    }
}
  • 添加controller业务

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

    • image.png
  • 快速访问http://localhost:8401/rateLimit/customerBlockHandler
    • image.png
  • 如果配置改为对GetMapping的资源名称的话会返回默认的代理

  • Sentinel主要有三个核心API

    • SphU定义资源
    • Tracer定义统计
    • ContextUtil定义了上下文

      9、服务熔断功能

  • sentinel整合ribbon+openFeign+fallback

    1、Ribbon系列

  • 启动nacos和sentinel

    1、新建cloudalibaba-provider-payment9003

  • 修改pom ```xml <?xml version=”1.0” encoding=”UTF-8”?> <project xmlns=”http://maven.apache.org/POM/4.0.0

       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    

      <artifactId>cloud2020</artifactId>
      <groupId>com.daijunyi</groupId>
      <version>1.0-SNAPSHOT</version>
    

    4.0.0 cloudalibaba-provider-payment9003 com.alibaba.cloud spring-cloud-starter-alibaba-nacos-discovery com.daijunyi cloud-api-commons ${project.version} org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-actuator org.springframework.boot spring-boot-devtools runtime true org.projectlombok lombok true org.springframework.boot spring-boot-starter-test test


- 修改yaml
```yaml
server:
  port: 9003

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

management:
  endpoints:
    web:
      exposure:
        include: '*'
  • 主启动类 ```java package com.daijunyi;

import com.daijunyi.entities.Payment; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

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


- 业务类
```java
package com.daijunyi.controller;

import com.daijunyi.entities.CommonResult;
import com.daijunyi.entities.Payment;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;

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

}
  • 复制一个9003位9004
    • 运行9003
    • image.png
    • 修改端口号为9004
    • image.png
    • image.png
    • 启动9004
    • image.png
    • nacos显示
      • image.png
  • 测试地址

  • 创建cloudalibaba-consumer-nacos-order84

  • 修改pom ```xml <?xml version=”1.0” encoding=”UTF-8”?> <project xmlns=”http://maven.apache.org/POM/4.0.0

       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    

      <artifactId>cloud2020</artifactId>
      <groupId>com.daijunyi</groupId>
      <version>1.0-SNAPSHOT</version>
    

    4.0.0

    cloudalibaba-consumer-nacos-order84

    org.springframework.cloud spring-cloud-starter-openfeign com.alibaba.cloud spring-cloud-starter-alibaba-nacos-discovery com.alibaba.cloud spring-cloud-starter-alibaba-sentinel com.daijunyi cloud-api-commons ${project.version} org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-actuator org.springframework.boot spring-boot-devtools runtime true org.projectlombok lombok true org.springframework.boot spring-boot-starter-test test


- 修改yaml
```yaml
server:
  port: 84


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

service-url:
  nacos-user-service: http://nacos-payment-provider
  • 主启动类 ```java package com.daijunyi;

import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.openfeign.EnableFeignClients;

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


- 业务类
   - ApplicationContextConfig
```java
package com.daijunyi.config;

import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class ApplicationContextConfig {

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}
  • CircleBreakerController ```java package com.daijunyi.controller;

import com.alibaba.csp.sentinel.annotation.SentinelResource; import com.alibaba.csp.sentinel.slots.block.BlockException; import com.daijunyi.entities.CommonResult; import com.daijunyi.entities.Payment; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;

@RestController public class CircleBreakerController {

@Value("${service-url.nacos-user-service}")
public String SERVICE_URL;

@Resource
private RestTemplate restTemplate;


@RequestMapping("/consumer/fallback/{id}")
//@SentinelResource(value = "fallback") //没有配置
//@SentinelResource(value = "fallback",fallback = "handlerFallback") //fallback只负责业务异常
//@SentinelResource(value = "fallback",blockHandler = "blockHandler") //blockHandler只负责sentinel控制台配置违规
@SentinelResource(value = "fallback",fallback = "handlerFallback",blockHandler = "blockHandler",
        exceptionsToIgnore = {IllegalArgumentException.class})
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);
}

}

<a name="QEk9k"></a>
#### 3、测试

- 服务列表
   - ![image.png](https://cdn.nlark.com/yuque/0/2021/png/12971636/1631179693088-36b46250-e108-41ec-9a93-8321e46cd0e1.png#clientId=ubabf230a-8a0d-4&from=paste&height=288&id=u4a95c439&margin=%5Bobject%20Object%5D&name=image.png&originHeight=576&originWidth=2858&originalType=binary&ratio=1&size=138761&status=done&style=none&taskId=u8438198d-e4a8-4896-85de-d1d57f739d5&width=1429)
- 访问[http://localhost:84/consumer/fallback/1](http://localhost:84/consumer/fallback/1)
   - ![image.png](https://cdn.nlark.com/yuque/0/2021/png/12971636/1631179760819-db40b14c-4fc3-453f-9b59-b7b1aaee94c8.png#clientId=ubabf230a-8a0d-4&from=paste&height=71&id=u4b47182f&margin=%5Bobject%20Object%5D&name=image.png&originHeight=142&originWidth=1782&originalType=binary&ratio=1&size=30509&status=done&style=none&taskId=u11f7a6e8-7862-4828-a8fe-2066ec5bc52&width=891)
- sentinel  dashbord    
   - ![image.png](https://cdn.nlark.com/yuque/0/2021/png/12971636/1631179834634-ec1f3a86-d5df-4072-b5e8-9e4a34bffdd6.png#clientId=ubabf230a-8a0d-4&from=paste&height=649&id=u0dbd7310&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1298&originWidth=2848&originalType=binary&ratio=1&size=238539&status=done&style=none&taskId=uf368655d-d92c-4568-b648-b66de6d4d1e&width=1424)
- 代码解析
   - 当配置了@SentinelResource(value = "fallback") //没有配置
      - 就是相当于只是一个资源路径,
         - 不会对默认的sentinel仪表盘的相关规则进行降级
         - 也不会对java运行时异常进行服务降级
   - 当配置@SentinelResource(value = "fallback",fallback = "handlerFallback") //fallback只负责业务异常
      - 对java异常会进行服务降级
      - 对sentinel仪表盘的规则错误显示默认配置
   - 当配置@SentinelResource(value = "fallback",blockHandler = "blockHandler") //blockHandler只负责sentinel控制台配置违规
      - 对java异常不会进行服务降级
      - 对sentinel仪表盘的规则会进行处理为自己的方法
   - @SentinelResource(value = "fallback",fallback = "handlerFallback",blockHandler = "blockHandler",<br />        exceptionsToIgnore = {IllegalArgumentException.class})
      - 对java异常进行服务降级
      - 对sentinel的违规规则进行自定方法的处理
<a name="swh0H"></a>
### 2、Feign系列

- 修改84模块
- 添加openfeign库
```xml
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
  • 修改yaml

    #开启sentinel对feign的支持
    feign:
    sentinel:
      enabled: true
    
  • 增加service openfeign接口 ```java package com.daijunyi.service;

import com.daijunyi.entities.CommonResult; import com.daijunyi.entities.Payment; import com.daijunyi.service.openfeign.PaymentFallbackService; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.stereotype.Service; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable;

@Service @FeignClient(name = “nacos-payment-provider”,fallback = PaymentFallbackService.class) public interface PaymentService {

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

}


- 增加实现类
```java
package com.daijunyi.controller;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.daijunyi.entities.CommonResult;
import com.daijunyi.entities.Payment;
import com.daijunyi.service.PaymentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;

@RestController
public class PaymentController {

    @Autowired
    private PaymentService paymentService;

    @RequestMapping("/consumer/payment/{id}")
    @SentinelResource(value = "payment",blockHandler = "blockHandler")
    public CommonResult<Payment> fallback(@PathVariable Long id) {
        CommonResult<Payment> result = paymentService.paymentSQL(id);
        return result;
    }

    //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);
    }

}
  • 此处服务降级用的openFeign
  • 限流控制用sentinel
  • 配置一个限流控制
    • image.png
  • 再修改一下9003进行睡眠20秒接口调用

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

    2、怎么配置

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

    3、步骤

    1、修改cloudalibaba-sentinel-service8401

  • 修改pom

    <dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-datasource-nacos</artifactId>
    </dependency>
    
  • 修改yaml ```yaml server: port: 84

spring: application: name: nacos-order-consumer cloud: nacos: discovery: server-addr: localhost:1111 sentinel: transport: dashboard: localhost:8080 port: 8719 datasource: #增加数据源配置 把sentinel流控规则持久化进nacos ds1: nacos: server-addr: localhost:1111 dataId: cloudalibaba-sentinel-service groupId: DEFAULT_GROUP data-type: json rule-type: flow

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

开启sentinel对feign的支持

feign: sentinel: enabled: true


- nacos进行配置

![image.png](https://cdn.nlark.com/yuque/0/2021/png/12971636/1631182521549-71880ca3-c7b5-4ceb-84e1-c8dcd890b293.png#clientId=ubabf230a-8a0d-4&from=paste&height=532&id=u1b6da6c0&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1064&originWidth=1534&originalType=binary&ratio=1&size=106041&status=done&style=none&taskId=u5a22c608-865e-4d7d-8fe2-03aa8fe0ff9&width=767)
```json
[
    {
         "resource": "/retaLimit/byUrl",
         "limitApp": "default",
         "grade":   1,
         "count":   1,
         "strategy": 0,
         "controlBehavior": 0,
         "clusterMode": false    
    }
]
  • image.png
  • 在sentinel中可以看到流控规则
  • image.png
    • 加入我们要修改这个count属性,只需要在nacos中修改一下,sentinel会自动同步
  • image.png
  • 查看sentinel控制台
  • image.png
    • 但是在sentinel中修改的值,是不会同步到nacos中的
  • 但是sentinel修改之后,nacos再次修改还是会同步到sentinel中