7

Spring Cloud Alibaba组件之Sentinel - 与牛竞技

 2 years ago
source link: https://www.cnblogs.com/gagaxiang/p/17014134.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Spring Cloud Alibaba组件之Sentinel

目录

一 引入Sentinel学习

二 Sentinel入门

三 搭建Sentinel Dashboard

四 Springboot项目接入Sentinel

五 接入限流埋点

六 限流配置

七 熔断降级

八 熔断降级Spring Cloud示例

九 黑白名单(授权规则) 

十 持久化

十一 Spring Cloud Alibaba Sentinel三种保护应用方式

一 引入Sentinel学习

提起Spring Cloud的限流降级组件,一般首先想到的是Netflix的Hystrix。

不过就在2018年底,Netflix宣布不再积极开发Hystrix,该项目将处于维护模式。官方表示1.5.18 版本的Hystrix已经足够稳定,可以满足Netflix 现有应用的需求,所以接下来其会把焦点转向对于自适应的实现,更多关注对应用程序的实时性能做出响应。对于新应用的熔断需求,将采用其它项目实现,Netflix推荐了Resilience4j。

作为Spring Cloud Netflix重要套件,Hystrix已经成为保障微服务稳定性的首选应用。其实除了Netflix和Resilience4j,限流降级还有一个新的选择,就是阿里巴巴的Sentinel组件。

二 Sentinel入门

官方文档:https://sentinelguard.io/zh-cn/docs/introduction.html

1 什么是Sentinel?

1.1 问题:

随着微服务的流行,服务与服务之间的调用稳定性变得越来越重要;

1、当服务访问量达到一定程度,流量扛不住的时候,该如何处理?(限流)

2、服务之间相互依赖,当服务B出现响应时间过长,影响到服务A的响应(A调用B),进而产生连锁反应,直至影响整个依赖链上的所有服务(雪崩),该如何处理?(熔断降级)

 这是分布式、微服务开发不可避免的问题。

1.2 Sentinel是什么?

Sentinel(分布式系统的流量防卫兵)是阿里开源的一套用于服务容错的综合性解决方案,随着微服务的流行,服务和服务之间的稳定性变得越来越重要。它以流量为切入点,从流量控制,熔断降级,系统负载保护等多个维度来保护服务的稳定性。

2 Sentinel的特征

1、丰富的应用场景:Sentinel承接了阿里巴巴近10年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围),消息削峰填谷。集群流量控制,实时熔断下游不可用应用等。

2、完备的实时监控:Sentinel提供了实时的监控功能。通过控制可以看到接入应用的单台机器秒级数据,甚至500台以下规模的集群的汇总运行情况。

3、广泛的开源生态:Sentinel提供开箱即用的与其他开源框架/库的整合模块,例如与SpringCLoud,Dubbo,gRPC的整合。只需要进入相应的依赖并进行简单的配置即可快速地接入Sentinel。

4、完善的SPI扩展点:Sentinel提供简单易用,完善的SPI扩展接口。您可以通过实现扩展接口来快速地定制逻辑。例如定制规则管理,适配动态数据源等。

3 Sentinel组成

Sentinel分为两个部分,具体如下:

1、核心库(Java客户端):不依赖任何框架/库,能够运行于所有Java运行时环境,同时对Dubbo/Spring Cloud等框架也有比较好的支持(你的微服务程序,可以直接添加sentinel.jar包)。

2、控制台(Dashboard)基于Spring Boot开发,打包后可以直接运行,不需要额外的Tomcat等应用容器(因为控制台是使用springboot开发,springboot内嵌了tomcat容器)。

这里我们先学习一下控制台的使用方式。

三 搭建Sentinel Dashboard

将应用接入Sentinel,最好搭建Sentinel控制台,可以在控制台上配置规则。

Dashboard是Alibaba写好的SpringBoot程序,我们直接下载启动即可.

1 下载Sentinel Dashboard

下载地址:https://github.com/alibaba/Sentinel/releases

1391607-20221230101201143-905822309.png

2 启动控制台

我们可以在Linux系统或者Windows系统启动Sentinel控制台,这里是直接在Windows上启动

#直接使用jar命令启动项目(控制台本身是一个SpringBoot项目)
java -Dserver.port=9090 -jar sentinel-dashboard-1.8.5.jar
其中,-Dserver.port=9090 代表控制台项目的端口号
1391607-20221230102300447-1139943844.png

3 访问控制台

启动Sentinel Dashboard通过地址和端口号控制台

http://localhost:9090/#/login
#如果在Linux上启动,ip需要对应上

输入默认用户名和密码(sentinel/sentinel),之后控制台可以看到sentinel-dashboard监控的指标。

如果要自定义用户名和密码,在启动命令加上设置用户名和密码参数即可,如下:

-Dsentinel.dashboard.auth.username=admin -Dsentinel.dashboard.auth.password=123456
1391607-20221230103105251-1861892838.png
1391607-20221230103230300-882233062.png

注意:默认启动后,控制台上没有任何服务被注册到控制台。在启动控制台时,可以通过参数设置将控制台本身注册到控制台上

-Dcsp.sentinel.dashboard.server=localhost:9090
-Dproject.name=sentinel-dashboard
# 其中:
# -Dcsp.sentinel.dashboard.server=localhost:9090 代表本控制台服务将会注册到自己的控制台
# -Dproject.name=sentinel-dashboard 代表本控制台服务的项目名称。
1391607-20221230103843806-347699653.png

我们可以看到控制台自身的服务已经注册到了控制台上。

默认情况下,Sentinel Dashboard 中的增加的配置规则是存储在内存中,重启后就会丢失;

Sentinel 会在客户端首次调用的时候进行初始化,开始向控制台发送心跳包,所以要确保客户端有访问量;

Sentinel Dashboard是一个独立的web应用(springboot开发的),可以接受客户端(微服务)的连接,然后与客户端(微服务)之间进行通讯,他们之间使用http协议进行通讯。

四 Springboot项目接入Sentinel

1 添加Sentinel依赖

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

项目其他关联的部分配置

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.3.12.RELEASE</version>
</parent>

<properties>
    <maven.compiler.source>8</maven.compiler.source>
    <maven.compiler.target>8</maven.compiler.target>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <java.version>1.8</java.version>
    <spring-cloud.version>Hoxton.SR12</spring-cloud.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>${spring-cloud.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

2 配置文件信息

server:
  port: 8081

spring:
  cloud:
    sentinel:
      transport:
     # 默认就是8719 port: 8719 dashboard: http://localhost:9090 web-context-unify: false application: name: sentinel-demo

配置文件说明:

spring.cloud.sentinel.transport.port端口配置会在应用对应的机器上启动一个Http Server,该 Server会与Sentinel控制台做交互。比如Sentinel控制台添加了1个限流规则,会把规则数据 push给这个Http Server接收,Http Server 再将规则注册到Sentinel 中。

spring.cloud.sentinel.transport.port:指定应用与Sentinel控制台交互的端口,应用本地会起一个该端口占用的HttpServer。

客户端需要添加jar包

<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-transport-simple-http</artifactId>
    <version>1.8.5</version>
</dependency>

spring-cloud-starter-alibaba-sentinel依赖已经包含了上面的依赖,所以上面的依赖不需要再单独添加。

1391607-20221230114210633-466349385.png

 3 新建控制类

1 @RestController
2 public class DemoController {
3     @GetMapping("/demo/message")
4     public String message(){
5         return "message";
6     }
7 }

4 启动项目,访问控制类接口

http://localhost:8081/demo/message

1391607-20230102092108736-1891787467.png

五 接入限流埋点

1 HTTP埋点

Sentinel starter 默认为所有的HTTP服务提供了限流埋点,如果只想对HTTP服务进行限流,那么只需要添加依赖,无需修改代码。(简单说就是所有的 controller 层接口默认提供限流埋点)

2 自定义埋点

如果需要对某个特定的方法进行限流或降级,可以通过 @SentinelResource 注解来完成限流的埋点,示例代码如下:

1 #service层
2 @Service
3 public class HelloServiceImpl implements HelloService {
4     @Override
5     @SentinelResource("hello")
6     public String hello() {
7         return "hello";
8     }
9 }
 1 #controller层
 2 @RestController
 3 public class HelloController {
 4     @Resource
 5     private HelloService helloService;
 6     @GetMapping("/hello")
 7     public String hello(){
 8         return helloService.hello();
 9     }
10 }

六 限流配置

1 认识流控规则

1391607-20230102093152517-1477953656.png

资源名:一般是我们的请求路径url或注解@SentinelResource的value属性值;

针对来源:来自于哪个应用;

阈值类型:分为QPS(每秒查询数)或并发线程数;

单机阈值:单个节点的QPS或线程数阈值;

是否集群:被请求的服务是否集群部署;

流控模式:

  1. 直接,就是直接对该资源进行控制;
  2. 关联,关联某一个资源(/app2),被关联的资源/app2达到阈值,则限制当前资源/test路径的访问;
  3. 链路,记录指定链路上的流量;

流控效果:

  1. 快速失败 ,直接限制;
  2. Warm Up,根据coldFactor(默认为3)的值,从阈值/coldFactor,经过预热的时长,才达到设置的QPS阈值,比如设置QPS阈值为100,那么100/3 =33,用33作为最初的阈值,然后在10秒到达100后再开始限流;
  3. 排队等待,在QPS阈值到达后,新的请求就等待,直到超时,可以适用于突发流量的请求;

2 直接限流

流量控制,其原理是监控应用流量的QPS(每秒查询率) 或并发线程数等指标,当达到指定的阈值时,对流量进行控制,以避免被瞬时的流量高峰冲垮,从而保障应用的高可用性。

2.1 添加限流规则

在Sentinel dashboard配置/demo/message的限流规则,每秒最多允许访问一次,超出访问,就会限流,返回默认的提示:Blocked by Sentinel (flow limiting)

1391607-20230103174639067-989927748.png

QPS(Query Per Second),QPS 其实是衡量吞吐量(Throughput)的一个常用指标,就是说服务器在一秒的时间内处理了多少个请求 —— 我们通常是指 HTTP 请求,显然数字越大代表服务器的负荷越高、处理能力越强。作为参考,一个有着简单业务逻辑(包括数据库访问)的程序在单核心运行时可以提供 50 - 100 左右的 QPS,即每秒可以处理 50 - 100 个请求。

TPS(Transaction Per Second) 每秒钟系统能够处理的事务的数量。

QPS(TPS):每秒钟 request/事务的数量  (此处 / 表示 或的意思)

并发数: 系统同时处理的request/事务数  (此处 / 表示 或的意思)

响应时间RT(Response Time):  一般取平均响应时间

理解了上面三个要素的意义之后,就能推算出它们之间的关系:

  QPS(TPS)= 并发数/平均响应时间  并发数除以平均响应时间

2.2 快速访问,查看效果

打开浏览器频繁访问(使用F5 刷新浏览器访问)(1秒内必须超过一次请求)

 

1391607-20230103174510992-629782732.png

3 关联限流

3.1 新建controller类

 1 @RestController
 2 @RequestMapping("/related")
 3 public class RelatedController {
 4     @GetMapping("/a")
 5     public String a(){
 6         return "关联限流a";
 7     }
 8     @GetMapping("/b")
 9     public String b(){
10         return "关联限流b";
11     }
12 }

3.2 新建关联限流规则

1391607-20230103175852373-1937873598.png

这里关联的资源是 /related/b(即保护接口b),上图设置表示:如果接口b的QPS达到单机阈值“1”,则开始通过限流接口“a”,从而保护“b”。

3.3 测试

测试时,可以快速的使用F5 来刷新b,快速的切换到a,F5再刷新a,发现a被限流了

当接口b发送并发流量QPS值小于1时,接口“a”可以正常访问。

关联限流规则是保护重要服务的措施,即:如果某个服务(b)达到临界值,则代表b资源不足,需要先限制不重要的服务(a),防止服务(a)继续调用服务(b)。

1391607-20230103175942776-1354751891.png

4 链路限流

4.1 新建服务类

1 @Service
2 public class HelloServiceImpl implements HelloService {
3     @Override
4     @SentinelResource("hello")
5     public String hello() {
6         return "hello";
7     }
8 }

4.2 新建controller类

 1 @RestController
 2 @RequestMapping("/chain")
 3 public class ChainController {
 4     @Resource
 5     private HelloService helloService;
 6     @GetMapping("/a")
 7     public String a(){
 8         return helloService.hello();
 9     }
10     @GetMapping("/b")
11     public String b(){
12         return helloService.hello();
13     }
14 }

4.3 新增配置文件application.yml

server:
  port: 8081

spring:
  cloud:
    sentinel:
      transport:
        port: 8719
        dashboard: http://localhost:9090
      # 禁止收敛URL的入口context,加上它否则链路规则不起作用
      web-context-unify: false
  application:
    name: sentinel-demo

4.4 新建链路流控规则

1391607-20230103192423150-1162029189.png

4.5 测试链路流控规则

访问接口a,当超过QPS设定值1,则接口“a”被限流,接口b同样调用方法,但是不会被限流。

限流时会出现500错误

1391607-20230103192715622-2015290978.png

七 熔断降级

上面实现了实现接口限流。但是在实际应用中,当我们的某个服务接口出现了问题,不能正常提供服务,或者该接口响应速度很慢,导致调用方大量请求堆积,此时需要将该接口降级服务,从而保护调用该接口的服务(消费者),快速返回降级结果,防止因为过多的服务等待该接口的返回,导致系统雪崩。

1391607-20230103194809467-1835840706.png

1 Sentinel熔断策略:慢调用比例

慢调用比例 (SLOW_REQUEST_RATIO):选择以慢调用比例作为阈值,需要设置允许的慢调用 RT(即最大的响应时间),请求的响应时间大于该值则统计为慢调用。当单位统计时长(statIntervalMs)内请求数目大于设置的最小请求数目,并且慢调用的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求响应时间小于设置的慢调用 RT 则结束熔断,若大于设置的慢调用 RT 则会再次被熔断。

1.1 名词解释:

调用:一个请求发送到服务器,服务器给与响应,一个响应就是一个调用

RT(Response Time):响应时间,指系统对请求作出响应的时间

慢调用:当调用的时间(响应的实际时间)>设置的RT时,这个调用叫做慢调用

慢调用比例:在所有调用中,慢调用占有实际的比例,= 慢调用次数 / 总调用次数

比例阈值:自己设定的 , 慢调用次数 / 总调用次数>=比例阈值

阈值(threshold value)又叫临界值,比如:水变成冰和水蒸气

统计时长:时间的判断依据

最小请求数:设置的调用最小请求数

1.2 状态转换

进入熔断状态判断依据:当统计时长内,实际请求数目大于最小请求数目,慢调用比例> 比例阈值,进入熔断状态

熔断状态:在接下来的熔断时长内请求会自动被熔断

探测恢复状态:熔断时长结束后进入探测恢复状态

结束熔断:在探测恢复状态,如果接下来的一个请求响应时间小于设置的慢调用 RT,则结束熔断;否则,继续熔断,等待进入探测恢复状态

1.3 实例测试

1.3.1 新建controller类

 1 @RestController
 2 public class PollyController {
 3     @GetMapping("/polly")
 4     public String polly(){
 5         try {
 6             Thread.sleep(1000);
 7         } catch (InterruptedException e) {
 8             e.printStackTrace();
 9         }
10         return "熔断降级";
11     }
12 }

1.3.2 配置熔断规则

1391607-20230103194222750-1551837295.png

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

熔断推测:

在1000毫秒,也就是1秒内,如果发送到/polly 的请求数数量大于1,并且在这些请求中,所有请求的响应时长(因为比例阈值为1,所以是所有的请求响应时长)都大于500毫秒,也就是都大于0.5秒的时候,进入熔断状态。

1.3.3 使用浏览器测试熔断

1391607-20230103194500705-1931634611.png

2 Sentinel熔断策略:异常比例

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

2.1 新建controller类

 1 @RestController
 2 @Slf4j
 3 public class ExceptionController {
 4     int i = 0;
 5     @GetMapping("/exception")
 6     public String exception(){
 7         i++;
 8         if (i % 3 == 0){
 9             throw new RuntimeException("出现异常");
10         }
11         log.info("i的值为:{}", i);
12         return "异常";
13     }
14 }

2.2 配置熔断规则

1391607-20230103200126353-295263457.png

 2.3 使用浏览器测试熔断

1391607-20230103200215679-1657811777.png

3 Sentinel熔断策略:异常数

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

3.1 配置熔断规则

1391607-20230103200513640-2064773038.png

3.2 使用浏览器测试熔断

1391607-20230103200629995-1697000811.png

八 熔断降级Spring Cloud示例

1 新建服务提供者工程

1.1 添加nacos依赖

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    <version>2.2.9.RELEASE</version>
</dependency>

1.2 添加配置文件

server:
  port: 8081

spring:
  application:
    name: sentinel-provider

  cloud:
    nacos:
      discovery:
        server-addr: http://IP地址:8848/nacos
        username: nacos
        password: nacos
        namespace: 75101df2-2f52-4100-aa37-f3c76a7fc1a0
        group: test-group

1.3 新建controller类

1 @RestController
2 @Slf4j
3 public class HelloController {
4     @GetMapping("/hello/{username}")
5     public String hello(@PathVariable String username){
6         log.info("我是一个服务提供者,我被调用了");
7         return username;
8     }
9 }

1.4 启动服务提供者

2 新建服务消费者工程

2.1 添加主要依赖

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    <version>2.2.9.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
    <version>2.2.9.RELEASE</version>
</dependency>

2.2 添配置文件

server:
  port: 8082

spring:
  application:
    name: sentinel-consumer

  cloud:
    nacos:
      discovery:
        server-addr: http://IP地址:8848/nacos
        username: nacos
        password: nacos
        namespace: 75101df2-2f52-4100-aa37-f3c76a7fc1a0
        group: test-group

    sentinel:
      transport:
        dashboard: http://localhost:9090
        port: 8719   #sentinel默认的与服务之间交互的接口
# 打开openfeign对sentinel的支持
feign:
  sentinel:
    enabled: true

2.3 新建feign接口

1 @FeignClient(value = "sentinel-provider", fallbackFactory = HelloFallbackFactory.class)
2 public interface HelloFeign {
3     @GetMapping("/hello/{username}")
4     String hello(@PathVariable String username);
5 }

2.4 新建FallbackFactory类

1 @Component
2 public class HelloFallbackFactory implements FallbackFactory<HelloFeign> {
3     @Override
4     public HelloFeign create(Throwable throwable) {
5         return username -> username + "说:我就是个被降级的";
6     }
7 }

2.5 新建controller类

1 @RestController
2 public class HelloController {
3     @Resource
4     private HelloFeign helloFeign;
5     @GetMapping("/hello/{username}")
6     public String hello(@PathVariable String username){
7        return helloFeign.hello(username);
8     }
9 }

2.6 启动服务消费者,使用浏览器进行测试

http://localhost:8082/hello/jack

可以正常访问

1391607-20230103214307858-1148016905.png

停止服务提供者,降级起作用了

1391607-20230103214222290-1446912871.png

九 黑白名单(授权规则)

很多时候,我们需要根据调用来源来判断该次请求是否允许放行,这时候可以使用Sentinel 的来源访问控制(黑白名单控制)的功能。来源访问控制根据资源的请求来源(origin)限制资源是否通过。

  1. 若配置白名单则只有请求来源位于白名单内时才可通过;
  2. 若配置黑名单则请求来源位于黑名单时不通过,其余的请求通过。

1 配置规则

1391607-20230103215431045-2090194781.png

来源访问控制规则(AuthorityRule)非常简单,主要有以下配置项:

resource:资源名,即限流规则的作用对象。

limitApp:对应的黑名单/白名单,不同origin 则用“,” 分隔,如 appA,appB。

strategy:限制模式,AUTHORITY_WHITE 为白名单模式,AUTHORITY_BLACK 为黑名单模式,默认为白名单模式。

2  新建controller类

1 @RestController
2 public class WhiteAndBlackController {
3     @GetMapping("/list")
4     public String hello(){
5         return "hello";
6     }
7 }

3 新增接口来源类

流控应用:Sentinel提供了RequestOriginParser来处理接口来源。

1 @Component
2 public class TestRequestOrigin implements RequestOriginParser {
3     @Override
4     public String parseOrigin(HttpServletRequest httpServletRequest) {
5         // 表示请求参数中含有server键
6         String server = httpServletRequest.getParameter("server");
7         return server;
8     }
9 }

4 配置白名单规则(黑名单的作用与白名单相反)

1391607-20230103221639955-29453705.png

 5 启动应用,使用浏览器访问

1391607-20230103221828514-624947373.png

只有当参数值与规则中配置的流控应用相等时,才能正常访问

1391607-20230103221847359-1154696689.png

十 持久化

默认情况下,sentinel-dashboard 中的规则是存储在微服务内存中,重启后就会丢失。

持久化指的是,一旦重启sentinel的微服务,sentinel配置的各种规则不会丢失。

1 Sentinel结合Nacos持久化配置

Sentinel持久化支持的类型有,详情见:

com.alibaba.cloud.sentinel.datasource.config.DataSourcePropertiesConfiguration
1391607-20230103223301779-1429627919.png

1.1 添加依赖

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

1.2 添加配置文件

  port: 8081

spring:
  cloud:
    nacos:
      discovery:
        server-addr: http://IP地址:8848/nacos
        username: nacos
        password: nacos
        namespace: 75101df2-2f52-4100-aa37-f3c76a7fc1a0
        group: test-group
    sentinel:
      transport:
        port: 8719
        dashboard: http://localhost:9090
      datasource:
        ds1:
          nacos:
            server-addr: http://IP地址:8848/nacos
            dataId: sentinel-datasource-nacos.json
            namespace: 75101df2-2f52-4100-aa37-f3c76a7fc1a0
            groupId: test-group
            # 只支持json和xml
            data-type: json
            #authority(授权规则)、degrade(降级规则)、flow(流控规则)、param(热点规则)、system(系统规则)五种规则持久化到Nacos中。 另外还增加网关的两个(api分组,限流)
            #rule-type这个属性没有提示,为空时,会报空指针错误
            rule_type: flow
  application:
    name: sentinel-datasource-nacos

1.3 登陆nacos,新建配置规则sentinel-datasource-nacos.json

[
{
"resource": "/user/findById",
"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---warmUp,2---排队等待

clusterMode:是否集群

参考官方文档:https://sentinelguard.io/zh-cn/docs/flow-control.html

  1. 此时如果是Nacos集群,每个节点务必要配置到同一个数据库上。并且保证每个节点都可用。如果有的节点宕掉了可能会导致配置持久化失败。
  2. 部署在nacos上的配置文件的名字并没有太多要求,只需要跟微服务项目中yml文件中配置的dataId一致即可。

1.4 查看sentinel流控规则,并测试访问

将配置规则持久化进Nacos保存,重启使用sentinel的微服务,只要访问一下基于流控规则的url,流控规则就会显示在sentinel的界面上。此时,持久化生效,只要Nacos里面的配置不删除,针对微服务上Sentinel上的流控规则持续

1391607-20230103224809216-1801392304.png
1391607-20230103224929874-286818552.png

1.5 问题

目前有一个小问题,当我们在sentinel dashboard控制台更新或者新加规则,nacos里面的规则并不能得到更新;

2 其他限流规则

2.1 Sentinel熔断降级规则说明

参考地址:https://sentinelguard.io/zh-cn/docs/circuit-breaking.html

2.2 Sentinel【热点规则】热点参数规则

参考地址:https://sentinelguard.io/zh-cn/docs/parameter-flow-control.html

2.3 Sentinel系统规则 

参考地址:https://sentinelguard.io/zh-cn/docs/origin-authority-control.html

十一 Spring Cloud Alibaba Sentinel三种保护应用方式

1 直接拦截我们所有controller的请求url路径

Sentinel为springboot程序提供了一个starter依赖,由于sentinel starter依赖默认情况下就会为所有的HTTP服务提供限流埋点,所以在springboot 中的Controller都可以受到Sentinel的保护;

只需为应用添加 spring-cloud-starter-alibaba-sentinel依赖,所有的HTTP接口都能获得Sentinel保护,当然,我们还需要为Sentinel配置保护的规则;底层通过一个拦截器对请求url进行拦截:

com.alibaba.csp.sentinel.adapter.spring.webmvc.SentinelWebInterceptor

可以通过如下配置关闭对微服务的保护:

#关闭sentinel对controller的url的保护

spring.cloud.sentinel.filter.enabled=false

2 通过代码方式保护应用(只是了解)

这种方式就是手动写代码,稍微比较繁琐

 1 @GetMapping("/test3/{app}")
 2 public String test3(@PathVariable("app") String app) {
 3    System.out.println("/test3/{app} --> " + app);
 4    Entry entry = null;
 5    try {
 6       entry = SphU.entry("test3");
 7       return restTemplate.getForObject("http://29-nacos-discovery-provider/test", String.class);
 8    } catch (BlockException e) {
 9       e.printStackTrace();
10       return "熔断降级了...";
11    } finally {
12       if (entry != null) {
13          entry.exit();
14       }
15    }
16 }

3 通过@SentinelResource(value = "app")注解保护应用

value

entryType

entry类型,标记流量的方向,取值IN/OUT,默认是OUT

blockHandler

处理BlockException的函数名称。函数要求:
1. 必须是 public
2.返回类型与原方法一致
3. 参数类型需要和原方法相匹配,并在最后加 BlockException 类型的参数。
4. 默认需和原方法在同一个类中。若希望使用其他类的函数,可配置 blockHandlerClass ,并指定blockHandlerClass里面的方法。

blockHandlerClass

存放blockHandler的类。对应的处理函数必须static修饰,否则无法解析,其他要求:同blockHandler。

fallback

用于在抛出异常的时候提供fallback处理逻辑。fallback函数可以针对所有类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处理。函数要求:
1. 返回类型与原方法一致
2. 参数类型需要和原方法相匹配,Sentinel 1.6开始,也可在方法最后加 Throwable 类型的参数。
3.默认需和原方法在同一个类中。若希望使用其他类的函数,可配置 fallbackClass ,并指定fallbackClass里面的方法。

fallbackClass

存放fallback的类。对应的处理函数必须static修饰,否则无法解析,其他要求:同fallback。

defaultFallback

用于通用的 fallback 逻辑。默认fallback函数可以针对所有类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处理。若同时配置了 fallback 和 defaultFallback,以fallback为准。函数要求:
1. 返回类型与原方法一致
2. 方法参数列表为空,或者有一个 Throwable 类型的参数。
3. 默认需要和原方法在同一个类中。若希望使用其他类的函数,可配置 fallbackClass ,并指定 fallbackClass 里面的方法。

exceptionsToIgnore

指定排除掉哪些异常。排除的异常不会计入异常统计,也不会进入fallback逻辑,而是原样抛出。

exceptionsToTrace

需要trace的异常

Throwable


Recommend

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK