Sentinel流控

news2024/10/5 13:01:28

Sentinel

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

1.sentinel特性

Sentinel 具有以下特征:

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

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

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

2. Sentinel控制台的安装

Sentinel提供一个轻量级的开源控制台,它提供机器发现以及健康情况管理、监控(单机和集群),规则管理和推送的功能。本节将详细记录何如通过Sentinel控制台控制Sentinel客户端的各种行为。Sentinel控制台的功能主要包括:流量控制、降级控制、热点配置、系统规则和授权规则等

2.1 下载Sentinel-dashboard

我们先去看对应的版本,从之前的章节,我们对应的springboot版本为2.6.3版,alibaba的2021.0.1.0版,所以去查看版本依赖,应该下载1.8.3的版本.

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

2.2 运行Sentinel-dashboard

因为是一个jar包,所以我们直接执行命令

java -jar sentinel-dashboard-1.8.3.jar

发现就是一个springboot项目,我们访问 http://localhost:8080

其中,用户名:sentinel 密码: sentinel

输入账号密码,就可以登录进去了,发现没有数据,因为需要有客户端上线才行,我们往下学习

2.3参数配置

更多可用的启动参数配置:
java -D参数名=参数值 -jar xx.jar
java -jar xx.jar --参数名=参数值
	-Dsentinel.dashboard.auth.username=sentinel用于指定控制台的登录用户名为 sentinel;
	-Dsentinel.dashboard.auth.password=123456用于指定控制台的登录密码为 123456,如果省略这两个参数,默认用户和密码均为 sentinel;
	-Dserver.servlet.session.timeout=7200用于指定 Spring Boot 服务端 session 的过期时间,如 7200 表示 7200 秒;60m 表示 60 分钟,默认为 30 分钟;
	-Dserver.port=8888 --修改服务启动端口
	-Dcsp.sentinel.dashboard.server=consoleIp:port 指定控制台地址和端口
例如:
java -Dserver.port=8888 -Dscp.sentinel.dashboard.server=localhost:8888 -jar sentinel.jar

3.sentinel的测试

sentinel的服务端已经搭建了,接下来创建项目,测试sentinel的流控,监控等功能。

3.1创建项目sentinel-client

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.8</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.powernode</groupId>
    <artifactId>01-sentinel-client</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>sentinel-client</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
        <spring-cloud-alibaba.version>2021.0.1.0</spring-cloud-alibaba.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>

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

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring-cloud-alibaba.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>
</project>

3.2配置文件application.yml

server:
    port: 8081
spring:
    application:
        name: sentinel-client
    cloud:
        sentinel:
            transport:      # sentinel的传输端口和控制面板地址
                port: 8719
                dashboard: 127.0.0.1:8080

spring.cloud.sentinel.transport.dashboard 指定了sentinel控制台的ip和端口地址;

spring.cloud.sentinel.transport.port代表sentinel客户端和控制台通信的端口,默认为8719,如果这个端口已经被占用,那么sentinel会自动从8719开始依次+1扫描,直到找到未被占用的端口。

启动时加入 JVM 参数 -Dcsp.sentinel.dashboard.server=consoleIp:port 指定控制台地址和端口。若启动多个应用,则需要通过 -Dcsp.sentinel.api.port=xxxx 指定客户端监控 API 的端口(默认是 8719)。

3.3创建控制器功能

@RestController
public class TestController {

    /**
     * 测试的接口
     *
     * @return
     */
    @GetMapping("hello")
    public String hello() {
        return "hello Sentinel";
    }
}

3.4启动访问

输入 http://localhost:8081/hello 后查看sentinel-dashboard

在这里插入图片描述

控制台已经显示正常了。在簇点链路中可以看到刚刚那次请求,我们可以对它进行流控、降级、授权、热点等配置(控制台是懒加载的,如果没有任何请求,那么控制台也不会有任何内容)

4.流控规则

先在簇点链路中找到/hello接口,选择流控

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7F0sfCYO-1672022489026)(images/13.jpg)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-azZzpjB4-1672022489027)(images/14.jpg)]

  • 资源名:标识资源的唯一名称,默认为请求路径,也可以在客户端中使用@SentinelResource配置;

  • 针对来源:Sentinel可以针对服务调用者进行限流,填写微服务名称即spring.application.name,默认为default,不区分来源;

  • 阈值类型、单机阈值:

 QPS(Queries-per-second,每秒钟的请求数量):当调用该api的QPS达到阈值的时候,进行限流;

 线程数:当调用该api的线程数达到阈值的时候,进行限流。

 是否集群:默认不集群;

流控模式

直接:当api调用达到限流条件的时,直接限流;

 关联:当关联的资源请求达到阈值的时候,限流自己;

 链路:只记录指定链路上的流量(指定资源从入口资源进来的流量,如果达到阈值,则进行限流)。
  • 流控效果
 快速失败:直接失败;

 Warm Up:根据codeFactor(冷加载因子,默认值为3)的值,从阈值/codeFactor,经过预热时长,才达到设置的QPS阈值;

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

4.1QPS快速失败

4.1.1 添加流控规则

规则:QPS
单机阈值:2  
流控模式:直接
流控效果: 快速失败

设置的效果是,1秒钟内请求/hello资源的次数达到2次以上的时候,进行限流。

4.1.2测试效果

现在我们快速访问 http://localhost:8081/hello

当手速快点的时候(1秒超过2次),页面返回Blocked by Sentinel (flow limiting)。并且响应码为429

4.1.3修改访问结果

默认返回是错误代码429,可以通过实现BlockExceptionHandler接口重写访问结果。

@Component
public class ServiceBlockExceptionHandler implements BlockExceptionHandler {

    /*处理BlockException类型以及子类类型的异常
     *
     * */
    @Override
    public void handle(HttpServletRequest request,
                       HttpServletResponse response,
                       BlockException e) throws Exception {
        // 设置响应数据编码
        response.setCharacterEncoding("utf-8");
        // 告诉客户端响应数据的类型,以及客户端显示内容的编码
        response.setContentType("text/html;charset=utf-8");
        Map<String,Object> map=new HashMap<>();
        map.put("status", 429);
        map.put("message","访问太频繁了");
        String jsonStr=new ObjectMapper().writeValueAsString(map);
        PrintWriter out = response.getWriter();
        out.print(jsonStr);
        out.flush();
        out.close();
    }
}

4.2 线程数快速失败

4.2.1修改Controller,模拟执行时长

我们模拟线程阻塞的情况,让线程不能及时回收,然后第二个请求线程进进来的时候就看出效果

/**
 * 测试的接口
 *
 * @return
 */
@GetMapping("hello")
public String hello() {
    try {
        TimeUnit.SECONDS.sleep(1);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return "hello Sentinel";
}

4.2.2 重启项目

修改controller以后重启项目,然后再添加流控规则,因为现在的所有规则都是临时的,然后重新访问一次/hello.

4.2.3添加流控规则

线程数:2 , 单机阈值:2 ,直接

这个配置效果是,当1s中有两个线程正在访问此接口,那么就会限流。测试快速访问,则抛出429

4.3 Warm Up 预热

流控效果除了直接失败外,我们也可以选择预热Warm Up。

Warm Up(RuleConstant.CONTROL_BEHAVIOR_WARM_UP)方式,即预热/冷启动方式。当系统长期处于低水位的情况下,当流量突然增加时,直接把系统拉升到高水位可能瞬间把系统压垮。通过”冷启动”,让通过的流量缓慢增加,在一定时间内逐渐增加到阈值上限,给冷系统一个预热的时间,避免冷系统被压垮。

sentinel客户端的默认冷加载因子coldFactor为3(源码写死了),即请求QPS从 threshold / 3 开始,经预热时长逐渐升至设定的QPS阈值。

4.3.1修改Controller

新增接口hello2


@GetMapping("hello2")
public String hello2() {
    return "hello Sentinel2";
}

4.3.2 重启测试访问后添加流控规则

资源:hello2
阈值:QPS, 单机阈值: 10, 流控模式:直接,流控效果:Warm Up 预热时长: 5

此流控效果为,前5s访问速度每秒超过3次就限流, 5s以后访问速度每秒超过10次(我们配置的)就限流

前期在预热环境,突然的高QPS 会导致系统直接拒绝访问,慢慢地,开始大量的接受新的请求。

4.4 排队等待

先删除上面的流控规则,然后重新添加流控规则

排队等待方式不会拒绝请求,而是严格控制请求通过的间隔时间,也就是让请求以均匀的速度通过

4.4.1修改controller

/**
 * 新增测试接口3
 *
 * @return
 */
@GetMapping("hello3")
public String hello3() {
    System.out.println(LocalDateTime.now().toLocalTime());
    return "hello Sentinel3";
}

4.4.2 重启后添加流控规则

资源:hello3
阈值:QPS, 
单机阈值: 1 
流控模式:直接
流控效果:排队等待
超时时间:2000

上述配置的含义是,访问/hello3请求每秒钟最多只能1次,超过的请求排队等待,等待超过2000毫秒则超时

4.4.3测试

查看控制台,每秒只有一个请求能进来

4.5关联

访问某个接口达到一定的流控规则后,开始限制本接口。关联中我们测试一下快速失败

4.5.1新增controller

我们新增两个controller,用于测试关联

/**
 * 测试关联的A接口
 *
 * @return
 */
@GetMapping("testA")
public String testA() {
    return "testA";
}

/**
 * 测试关联的B接口
 *
 * @return
 */
@GetMapping("testB")
public String testB() {
    return "testB";
}

4.5.2 重启后添加流控规则

资源:/testA
阈值:QPS, 
单机阈值: 3 
流控模式:关联
关联资源:/testB
流控效果:快速失败

上述配置的含义是,访问/testB接口请求每秒钟超过3次,那么限流/testA接口

4.5.3测试访问

快速访问/testB接口 然后尽快访问/testA,发现/testA已经限流了

4.6链路

程序的调用可以看成为一条链路。当触发链路的某条规则后,该链路被限流。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jBoLREJU-1672022489027)(images/15.jpg)]

上图从API 出发,可以发现有2 条链路,分别为:

Link1–>hello–>other

Link2–>hello–>other

2 条链路在调用上,限流规则互补影响。

4.6.1 新增一个service和实现类

@Service
public class HelloServiceImpl implements HelloService{
    /**
     * 我们使用@SentinelResource(value = "hello")标记为此方法为一个资源
     *
     * @return
     */
    @SentinelResource(value = "hello",blockHandler = "blockMethod")
    public String hello() {
        return "hello";
    }

    public String blockMethod(BlockException e) {
        System.out.println(e.getMessage());
        return "访问太快啦";
    }
}

4.6.2修改controller

@Autowired
private HelloServiceImpl helloService;
/**
 * 新增link1接口
 */
@GetMapping("link1")
public String link1() {
    String hello = helloService.hello();
    return "我是link1调用hello的结果" + hello;
}
/**
 * 新增link2接口
 
 */
@GetMapping("link2")
public String link2() {
    String hello = helloService.hello();
    return "我是link2调用hello的结果" + hello;
}


4.6.3修改配置文件

server:
    port: 8081
spring:
    application:
        name: sentinel-client
    cloud:
        sentinel:
            transport:
                port: 8719
                dashboard: 127.0.0.1:8080
            web-context-unify: false # 关闭context整合

4.6.4重启访问

http://localhost:8081/link1

http://localhost:8081/link2

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yQDkT47m-1672022489027)(images/16.jpg)]

4.6.5添加流控规则

资源:hello
阈值:QPS, 
单机阈值: 2
流控模式:链路
入口资源:/link1
流控效果:快速失败

在入口资源,我们使用的是/link1,点击新增,完成对规则的添加。

上述配置的意思是,当通过/link1访问hello的时候,QPS大于2则进行限流;

言外之意就是/link2访问hello请求并不受影响。

5. 熔断规则

Sentinel除了流量控制以外,对调用链路中不稳定的资源进行熔断降级也是保障高可用的重要措施之一。由于调用关系的复杂性,如果调用链路中的某个资源不稳定,最终会导致请求发生堆积。Sentinel 熔断降级会在调用链路中某个资源出现不稳定状态时(例如调用超时或异常比例升高),对这个资源的调用进行限制,让请求快速失败,避免影响到其它的资源而导致级联错误。当资源被降级后,在接下来的熔断时间窗口之内,对该资源的调用都自动熔断(默认行为是抛出 DegradeException)。

当访问系统失败超过一定的次数后,对该接口进行熔断的操作。

我们可以发现,降级策略分为3种:

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

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

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

5.1RT

当 1s 内持续进入 5 个请求,对应时刻的平均响应时间(秒级)均超过阈值(count,以 ms 为单位),那么在接下的时间窗口(DegradeRule 中的 timeWindow,以 s 为单位)之内,对这个方法的调用都会自动地熔断(抛出 DegradeException)

5.1.1 新增一个controller

/**
 * testRt接口
 *
 * @return
 */
@GetMapping("testRt")
public String testRt() {
    try {
        TimeUnit.SECONDS.sleep(1);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return "测试RT";
}

5.1.2 增加降级规则

先重启动项目,然后访问一次后,再新增降级规则

资源名: /testRt
熔断策略:慢调用比例
最大RT: 500
阈值: 1
熔断时长: 2
最小请求数:5
统计时长:5000

上述配置的含义是,访问/testRt 如果1s内五次请求的响应时间都超过500ms,就限流5s

  1. 如果有一个请求响应时间超过设置的rt(500ms)

  2. 那么就会判断接下来的一个时间窗口(5s)内,前5个请求的平均响应时间是否超过rt

  3. 如果超过了,进行预熔断,再次判断下个时间窗口内的前5个请求是否超过平均响应时间

  4. 如果超过了,接下来的请求会被熔断

  5. 经过熔断时长(2s,时间窗口的值)后,进入探测恢复状态(HALF-OPEN)阶段,即接下来的一个请求响应时间小于rt,则熔断结束,否则会再次被熔断

5.1.3测试访问

访问 http://localhost:8081/testRt 快速访问5次,后面就的就限流了,过2s后又可以继续访问了

5.2 异常比例

当资源的每秒请求量 >= 5,并且每秒异常总数占通过量的比值超过阈值之后,资源进入熔断状态,在接下来的时间窗口内,程序都会快速失败。

5.2.1 新增一个controller

/**
 * testEx接口
 *
 * @return
 */
@GetMapping("testEx")
    public String testEx() {
        int count= new Random().nextInt(100);
        if(count%2==0)
           throw new RuntimeException("就是不想成功");
        return "奇数:"+count;
    }


5.2.2 增加降级规则

先重新项目,然后访问一次后,再新增熔断规则

资源名: /testEx
熔断策略:异常比例
比例阈值: 0.5
熔断时长: 3
最小请求数:5
统计时长:3000

上面的配置含义是:如果/testEx的QPS大于5,并且每秒钟的请求异常比例大于50%的话,那么在未来的3秒钟(时间窗口)内,sentinel断路器打开,该api接口不可用。

也就是说,如果一秒内有10个请求进来,超过5个以上都出错,那么会触发熔断,3秒钟内这个接口不可用。

5.2.3测试访问

多次快速请求后出现限流,5s窗口期过了以后,又可以访问了

5.3 异常数量

当指定时间窗口内,请求异常数大于等于某个值时,触发熔断。继续使用上面的接口测试。

删除之前的规则,新增规则

5.3.1 增加降级规则

资源名: /testEx
熔断策略:异常数
异常数: 5
熔断时长: 3
最小请求数:5
统计时长:10000

上述配置的含义是,访问/testEx 如果10s内访问接口出现异常超过5次,就熔断

5.3.2 测试访问

在10s内访问第6次就出现了限流

6 系统规则

系统规则则是针对整个系统设置限流规则,并不针对某个资源,设置页面如下:

阈值类型包含以下五种:

  • Load 自适应(仅对 Linux/Unix-like 机器生效):系统的 load1 作为启发指标,进行自适应系统保护。当系统 load1 超过设定的启发值,且系统当前的并发线程数超过估算的系统容量时才会触发系统保护(BBR 阶段)。系统容量由系统的 maxQps minRt 估算得出。设定参考值一般是 CPU cores 2.5。
  • 平均 RT:当单台机器上所有入口流量的平均 RT 达到阈值即触发系统保护,单位是毫秒。
  • 并发线程数:当单台机器上所有入口流量的并发线程数达到阈值即触发系统保护。
  • 入口 QPS:当单台机器上所有入口流量的 QPS 达到阈值即触发系统保护。
  • CPU usage(1.5.0+ 版本):当系统 CPU 使用率超过阈值即触发系统保护(取值范围 0.0-1.0),比较灵敏。

7.Sentinel集成openfeign【重点】

我们使用nacos做注册中心,openfeign做远程调用,sentinel做限流熔断,和hystrix一样,只需要在配置文件修改开启feign对sentinel的支持即可

7.1创建提供者sentinel-provider

7.1.1pom文件

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.8</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.powernode</groupId>
    <artifactId>02-sentinel-provider</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>sentinel-provider</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
        <spring-cloud-alibaba.version>2021.0.1.0</spring-cloud-alibaba.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring-cloud-alibaba.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>

</project>


7.1.2配置文件application.yml

server:
    port: 8001
spring:
    application:
        name: sentinel-provider
    cloud:
        nacos:
            server-addr: localhost:8848

7.1.3修改启动类

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

7.1.4 创建一个controller


@RestController
public class ProviderController {

    @GetMapping("provider")
    public String provider(String name) {
        return "我是提供者" + name;
    }
}

7.1.5启动项目

7.2修改sentinel-client项目

7.2.1 修改pom.xml

完整的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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.8</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.powernode</groupId>
    <artifactId>01-sentinel-client</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>sentinel-client</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>2021.0.1</spring-cloud.version>
        <spring-cloud-alibaba.version>2021.0.1.0</spring-cloud-alibaba.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </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-nacos-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-loadbalancer</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </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>

            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring-cloud-alibaba.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>

</project>


7.2.2 修改配置文件

server:
    port: 8081
spring:
    application:
        name: sentinel-client
    cloud:
        sentinel:
            transport:      # sentinel的传输端口和控制面板地址
                port: 8719
                dashboard: 127.0.0.1:8080
        nacos:
            server-addr: localhost:8848
feign:
    sentinel:
        enabled: true   # 开启feign对sentinel的支持

7.2.3修改启动类,开启feign

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

7.2.4添加feign接口

@FeignClient(value = "sentinel-provider", fallback = ProviderFeignSentinel.class)
public interface ProviderFeign { 
    @GetMapping("provider")
    String provider(@RequestParam("name") String name);
}

7.2.5添加feign熔断

@Component
public class ProviderFeignSentinel implements ProviderFeign {
    
    @Override
    public String provider(String name) {
        return "我走了sentinel的熔断方法";
    }
}

7.2.6 修改controller

@Autowired
private ProviderFeign providerFeign;

@GetMapping("testRpc")
public String testRpc(String name) {
    String provider = providerFeign.provider(name);
    return provider;
}


7.2.7启动测试

http://localhost:8081/testRpc?name=bjpowernode

至此sentinel集成openfeign完成,如果远程服务不可用,则启用熔断方法

8.Sentinel整合gateway完成限流

在gateway中使用了redis来完成限流,sentinel在1.6.0以后也主动支持了gateway完成限流功能,使用起来很方便.

8.1新建一个gateway服务,并且注册到nacos

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.powernode</groupId>
    <artifactId>04-gateway</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>gateway</name>
    <description>Demo project for Spring Boot</description>
   <properties>
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <spring-boot.version>2.6.8</spring-boot.version>
        <spring-cloud-alibaba.version>2021.0.1.0</spring-cloud-alibaba.version>
        <spring-cloud.version>2021.0.1</spring-cloud.version>
    </properties>

    <dependencies>
         <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-sentinel-datasource</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</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>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring-cloud-alibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <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>
</project>

8.2 修改application.yml配置文件

server:
    port: 80
spring:
    application:
        name: gateway
    cloud:
        gateway:
            enabled: true
            discovery:
                locator: # 开启动态路由,可以通过服务名称做发现从而路由
                    enabled: true
                    lower-case-service-id: true
            routes:  # 写一个测试路由
                -   id: test-id
                    uri: lb://sentinel-provider
                    predicates:
                        - Path=/provider/**
        nacos:
            username: nacos
            password: nacos
            server-addr: localhost:8848
        sentinel:
            transport:
                dashboard: localhost:8080
                port: 8719
            scg: # 限流后的处理
                fallback:
                    ## 两种模式,一种是response返回文字提示信息,
                    ## 一种是redirect,重定向跳转,需要同时配置redirect(跳转的uri)
                    mode: response
                    response-status: 200
                    response-body: '{"code": 429,"msg": "limited"}'
                    content-type: application/json


8.3 限流模式

实现限流机制主要由GatewayFlowRule与ApiDefinition两个核心类实现配置:

  • GatewayFlowRule(Route ID): 网关限流规则,针对 API Gateway 的场景定制的限流规则,可以针对不同 route 或自定义的 API 分组进行限流,支持针对请求中的参数、Header、来源 IP 等进行定制化的限流。

  • ApiDefinition(Api分组): 用户自定义的 API 定义分组,可以看做是一些 URL 匹配的组合。比如我们可以定义一个 API 叫 my_api,请求 path 模式为 /foo/** 和 /baz/** 的都归到 my_api 这个 API 分组下面。限流的时候可以针对这个自定义的 API 分组维度进行限流。

    8.3.1 Route-id模式

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Fprd8l6b-1672022489028)(images/17.jpg)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BT1z8KVW-1672022489028)(images/18.jpg)]

然后快速访问 http://localhost/provider 后出现限流

8.3.2 Api分组模式

1 .新增api分组

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LtNmQJk8-1672022489029)(images/19.jpg)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-F8cHUvzl-1672022489029)(images/20.jpg)]

  1. 添加流控规则

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

3.测试

快速访问 http://localhost/sentinel-provider/provider,出现限流

8.4持久化限流配置

我们在控制台添加的限流配置是临时的,在实际生产环境中可以使用nacos来做限流配置的持久化方案,我们可以将限流配置写在nacos的配置文件管理中。

提示信息,
## 一种是redirect,重定向跳转,需要同时配置redirect(跳转的uri)
mode: response
response-status: 200
response-body: ‘{“code”: 429,“msg”: “limited”}’
content-type: application/json


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/115312.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

最优化方法——最小二乘法与梯度下降法

目录 系列文章目录 一、问题 二、实验思路综述 1.实验工具及算法 2.实验数据 3.实验目标 4.实验步骤 三、最小二乘问题引入 1.最小二乘问题样例 2.最小二乘问题解决方案及数学模型化 3.相关线性代数知识导入 3.1 梯度 3.2 矩阵的逆 3.3 QR分解 四、最小二乘法 …

用 ChatGPT 运行 Python

最近&#xff0c;我一直在阅读一些关于ChatGPT的有趣文章。在一篇文章中&#xff0c;有人发明了一种新的语言&#xff0c;并让ChatGPT运行它。在另一篇文章中&#xff0c;有人在ChatGPT中运行一个虚拟机。后者启发我提出了下面这个问题。你能在ChatGPT中运行一个交互式Python会…

【docker常用命令】

一、帮助启动类命令 &#xff08;1&#xff09;启动docker systemctl start docker&#xff08;2&#xff09;停止docker systemctl stop docker&#xff08;3&#xff09;重启docker systemctl restart docker&#xff08;4&#xff09;查看docker状态 systemctl status…

【数据预处理】基于Pandas的数据预处理技术【california_housing加州房价数据集】_后9个任务

文章目录一.需求分析二.需求解决2.1 对第一个特征&#xff08;收入中位数&#xff09;排序后画散点图2.2 对第一个特征&#xff08;收入中位数&#xff09;画分位数图并分析2.3 【选做】对所有特征画分位数图并进行分析2.4 使用线性回归方法拟合第一个特征&#xff08;收入中位…

基于c# asp.net电子病历管理系统的设计与实现

摘 要 网络的广泛应用给生活带来了十分的便利。所以把电子病历管理与现在网络相结合&#xff0c;利用net语言建设电子病历管理系统&#xff0c;实现电子病历管理的信息化。则对于进一步提高医院的发展&#xff0c;丰富电子病历管理经验能起到不少的促进作用。 电子病历管理系统…

AbstractQueueSynchronizer

AbstractQueueSynchronizer AbstractQueueSynchronizer 是基于 FIFO线程等待队列 的一个同步器开发框架。 这篇文章首先介绍同步器概念&#xff0c;然后介绍AQS的结构原理 什么是Synchronizer&#xff08;同步器&#xff09; 并发环境下&#xff0c;Synchronizer用于实现线…

Windows和Mac系统实现本地部署WebPageTest工具

在项目开发或者测试的过程中&#xff0c;由于没有上线&#xff0c;我们在公网上无法访问我们的网站&#xff0c;但同时我们又需要查看浏览器性能&#xff0c;这样我们就需要在本地部署WebPageTest工具以协助进行性能测试 具体实现步骤&#xff1a; Windows系统&#xff1a; …

FFT求多项式乘积

之前在b站上看到了一些介绍FFT的视频 《快速傅里叶变换(FFT)——有史以来最巧妙的算法&#xff1f;》 《这个算法改变了世界》 于是打算写一篇记录一下qwq&#xff08;本博客中的截图基本上来源于第一个视频&#xff09; Fast Fourier Transform 是一种能在O(nlogn)O(nlogn)…

企业营销数字化转型:如何转型、如何选品、如何用好?

省时查报告-专业、及时、全面的行研报告库省时查方案-专业、及时、全面的营销策划方案库【免费下载】2022年11月份热门报告盘点2023年&#xff0c;如何科学制定年度规划&#xff1f;《底层逻辑》高清配图清华大学256页PPT元宇宙研究报告.pdf&#xff08;附下载链接&#xff09;…

【LeetCode】1759. 统计同构子字符串的数目

统计同构子字符串的数目 题目描述 给你一个字符串 s &#xff0c;返回 s 中 同构子字符串 的数目。由于答案可能很大&#xff0c;只需返回对 109 7 取余 后的结果。 同构字符串 的定义为&#xff1a;如果一个字符串中的所有字符都相同&#xff0c;那么该字符串就是同构字符串…

自定义报表-FineReport JS实现隐藏Tab页

1. 概述 1.1 问题描述 在实际项目中&#xff0c;使用决策报表的时候&#xff0c;有时会用到在决策报表参数面板获取报表控件的值&#xff0c;那么该如何实现呢&#xff1f; 1.2 实现思路 使用 JS 获取报表主体的控件值&#xff1a; _g().getWidgetByName("area").…

【金猿人物展】数睿数据创始人兼CEO穆鸿:大数据价值创造关键在于应用普惠...

‍穆鸿本文由数睿数据创始人兼CEO穆鸿撰写并投递参与“数据猿年度金猿策划活动——2022大数据产业趋势人物榜单及奖项”评选。‍数据智能产业创新服务媒体——聚焦数智 改变商业事情还得从我2022年这一年经历的一些事情谈起&#xff0c;由于工作的原因&#xff0c;我要经常往返…

Python量化交易04——基于机器学习的交易策略

参考书目:深入浅出Python量化交易实战 学量化肯定要用的上机器学习这种强大的预测技术。本次使用机器学习构建一些简单的预测进行量化交易&#xff0c;使用Python进行回测。 获取数据 import pandas as pd import tushare as ts import numpy as npfrom sklearn.neighbors imp…

线程池设计与实现C

线程池实现 结构设计 先上图&#xff1a; 参数 线程池&#xff1a; 包含一个执行队列、一个任务队列mutex用来在多个线程取任务时锁任务队列&#xff0c;cond用来在任务队列为空时锁任务队列 如线程A锁了任务队列&#xff0c;去取任务时&#xff0c;又发现任务队列为空&…

【C++求解数学题】大圆圈里面三角形个数相等

本文介绍的问题是一道来自于二年级&#xff08;上&#xff09;数学的练习题。 问题 在下图中画8个Δ\DeltaΔ,使每个大圆圈里都有4个Δ\DeltaΔ. 示例&#xff1a; 每个大圆圈里面均有4个Δ\DeltaΔ. 方法 按照“变量-范围-条件”的三段式穷举法解题框架&#xff0c;对…

分布式系列之聊聊Nginx实现原理

Nginx作为开源的轻量级的HTTP服务器&#xff0c;广泛应用于分布式应用架构中。本文简要介绍了Nginx的特点及使用场景、Nginx的进程模型和请求处理流程&#xff0c;并结合不同场景进行配置&#xff0c;对Nginx的架构和实现原理有个初步的了解。 1、Nginx是什么 Nginx&#xff0…

Echarts之甘特图type: ‘custom‘参数详解

甘特图 const groupData XEUtils.groupBy(data, "eqpName"); //分组后的数据 const yAxisData Object.keys(groupData); const seriesData Object.keys(groupData).map((item, index) > {let arr [];groupData[item].forEach((GItem) > {arr.push([index,f…

Graphviz安装向导及入门指南

目录 1、首先在官网下载graphviz 2、安装。 3、测试并在Windows命令行中使用 4、在Python中使用 5、在自带的gvedit.exe 程序中使用 6、在语雀中使用 7、绘制一棵简单的二叉树 8、详细语法介绍 8.1 带标签 8.2 修改方框颜色和形状 8.3子视图 8.4 结构视图 8.5 …

【网络安全】Centos7安装杀毒软件----ClamAV

一、ClamAV介绍 Clam AntiVirus是一个Linux系统上使用的反病毒软件包。主要应用于邮件服务器&#xff0c;采用多线程后台操作&#xff0c;可以自动升级病毒库。 二、安装 1.下载rpm wget https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm 2.升级epe…

4.1、网络层概述

1、主要任务 网络层的主要任务是实现网络互连\color{red}实现网络互连实现网络互连&#xff0c;进而实现数据包在各网路之间的传输\color{red}实现数据包在各网路之间的传输实现数据包在各网路之间的传输 例如&#xff1a; 这些异构型网络若只是需要各自内部通信&#xff0c…