其他分享
首页 > 其他分享> > sentinel实现限流、降级、熔断配置和测试使用

sentinel实现限流、降级、熔断配置和测试使用

作者:互联网


sentinel实现限流、降级、熔断配置和测试使用

这篇是转载自:https://blog.csdn.net/qq_38322527/article/details/106253143
我仔仔细细的看了两遍,简直良心好文

一、Sentinel简介

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

Sentinel github开源代码和文档介绍

[问:]Sentinel 与 Hystrix 存在哪些不同?

Hystrix 需要引入大量的pom依赖,以及需要在配置文件中做一定量的配置编写;其次使用流量监控等操作时,需要额外配置很多,过于麻烦。
Sentinel 只需要引入对应pom依赖即可,能够在界面上直接进行配置,无需写太多的配置文件。

在这里插入图片描述

二、Sentinel 下载、安装和使用

2.1、下载sentinel

下载链接

端口占用为 8080 (与tomcat类似)
这是一个jar项目,使用 java -jar xxxxx.jar 启动

在这里插入图片描述
查看配置文件,并无端口号相关的配置信息,采取的是Springboot 默认的 8080端口启动。

[注意:]Sentinel需要额外注意端口信息

尝试采取指定端口号启动方式,但无效;可能是官方出现的隐藏bug。
后期如做配置,需要额外注意Sentinel 的端口信息

2.2、启动 Nacos、Sentinel

java -jar sentinel-dashboard-1.7.2.jar

访问:

localhost:8080
在这里插入图片描述
账号、密码分别为:sentinel

2.3、创建测试项目

创建子项目 cloudalibaba-Sentinel-Server-8500

引入依赖信息:

<!-- SpringCloud ailibaba nacos -->
        <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-web</artifactId>
        </dependency>
        <!--监控 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!--   使用 openfeign 组件  -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <!--  使用 Sentinel 组件 -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>
        <!--  sentinel 的数据持久化  -->
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-datasource-nacos</artifactId>
        </dependency>

    

编写配置文件信息,指明当前微服务的端口、服务别名以及让Sentinel监听当前微服务。

## 该服务的端口信息
server:
  port: 8500

## 服务别名和nacos服务注册发现地址配置
spring:
  application:
    name: cloudalibaba-sentiner-server
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
    sentinel:  ## 流控
      transport:
        # sentinel dashboard的地址(sentinel的地址--8080监控当前8500微服务)
        dashboard: localhost:8080
        # 为应用开启额外的端口,上报监控信息
        # 默认为8719端口,加入被占用将会自动从8719开始+1扫描,直至找到未被占用的端口地址
        port: 8719

## 监控相关
management.endpoints.web.exposure.include: '*'

编写启动类和测试类:

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

@SpringBootApplication
@EnableDiscoveryClient
public class SentinelApplication8500 {
    public static void main(String[] args) {
        SpringApplication.run(SentinelApplication8500.class,args);
    }
}
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController {

    @RequestMapping("/test1")
    public String test1(){
        return "----this is test1";
    }

    @RequestMapping("/test2")
    public String test2(){
        return "----this is test2";
    }
}

2.4、启动测试项目

启动测试项目 cloudalibaba-Sentinel-Server-8500
在nacose中完成了服务的注册:
在这里插入图片描述
查看Sentinel,但是并无监控信息。

Sentinel是一款 懒加载 式的架构,需要对接口进行请求后,才能获得相关监控信息。

请求接口后再次刷新Sentinel并查看信息统计:

http://localhost:8500/test2
http://localhost:8500/test1

在这里插入图片描述

三、Sentinel 阈值类型和流控模式

在这里插入图片描述
界面配置专业词汇概述:

名称介绍注意项
资源名唯一名称默认为请求路径
针对资源Sentinel可以针对调用者进行限流,填写微服务名默认为default
阈值类型 QPS每秒钟的请求数量当调用该api的QPS达到阈值时,进行限流操作
阈值类型 线程数当调用该api的请求线程数达到阈值时,触发限流
流控模式 直接当api达到限流条件时,直接限流。
流控模式 关联当关联的资源达到阈值时,就限流自己。
流控模式 链路当从某个接口过来的资源达到限流条件时,开启限流。
流控效果 快速失败直接进行失败,抛出异常。
流控效果 Warm Up根据codeFactor(冷加载因子,默认为3)的值,从阈值/codeFactor,经过预热时长,才达到设置的QPS阈值。
流控效果 排队等待匀速排队,让请求以匀速的速度通过,阈值类型必须设定为QPS,否则无效

3.1、阈值类型 QPS、流控模式 直接

修改 /test1 请求的流控规则,如下图所示:
在这里插入图片描述
默认的高级设置为:
在这里插入图片描述

每秒允许请求数为 1

在这里插入图片描述
请求并进行测试:

测试需要讲究快速点击缓慢点击

表示1秒内,查询1次请求OK;
如果请求在1秒内的次数高于1次,则进入快速失败流程,报默认的错误提示!

3.2、阈值类型 线程数、流控模式 直接

修改 /test1 的请求限流配置,将QPS更改为线程数
在这里插入图片描述
在这里插入图片描述
再次请求:

http://localhost:8500/test1
在这里插入图片描述

发现:

无论请求速率多么快,都不会进入限流回执

[问:]这是为什么?
分析问题前,需要了解 QPS线程数这两种方式的区别:

类型区别描述关键
QPS假设100个请求同时过来,QPS设置一秒一个请求线程通过,1秒内其他请求直接进行拦截。每秒请求数
线程数假设100个请求同时过来,线程数允许所有的请求进入,但每次只允许一个请求执行操作,其他请求数等待。最大请求数

修改处理接口:

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController {

    @RequestMapping("/test1")
    public String test1(){
        return "----this is test1";
    }

    @RequestMapping("/test2")
    public String test2(){
        return "----this is test2";
    }

    /**
     * 模拟  阈值类型  为  线程数
     * @return
     */
    @RequestMapping("/test3")
    public String test3(){
        // 每次请求过来,都延时800毫秒做处理
        try {
            Thread.sleep(800);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "----this is test3";
    }
}

再次请求测试:

http://localhost:8500/test3
快速点击!
在这里插入图片描述

3.3、阈值类型 QPS、流控模式 关联

此次的配置采取如下方式:

当关联的资源达到限流条件时,开启限流
配置请求 /test2 限流QPS,关联 /test1
在这里插入图片描述

文档解释现象:

/test1 与 /test2 有关联关系。
若 /test2 达到阈值时,会对 /test1 进行限流

实用背景:

下单和支付接口进行关联。
如若支付接口达到阈值,就限定下单接口少产生支付接口,缓解压力!
在这里插入图片描述

在这里插入图片描述
如何进行测试呢?

1、正常请求 /test1,无关乎快速还是缓慢,都会是正常返回信息。
2、循环不断请求/test2,触发该接口的限流操作。
3、再次请求/test1,查看请求回执状态信息。

正常请求/test1

http://localhost:8500/test1
无论快慢,都是返回下列信息!
在这里插入图片描述

使用postman、jmeter等工具,迭代请求/test2,触发限流后,再次请求/test1查看回执状态信息:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
运行 postman,浏览器访问:http://localhost:8500/test1

现象:

在这里插入图片描述
在这里插入图片描述
/test2触发了限流,此时的/test1请求将会受到影响!
/test2限流结束,/test1才能继续请求得到回执!

3.4、QPS、链路

链路:当从某个接口过来的资源达到限流条件时,开启限流。

链路流控是针对上级接口

[注意:]此处有巨坑!

1、Sentinel 从 1.6.3版本开始,Sentinel Web Filter 默认收敛所有URL的入口Context,因此链路限流不生效。
2、1.7.0版本开始,官方在CommomFilter中引入了一个WEB_CONTEXT_UNIFY参数,用于控制是否收敛context。默认为true(默认收敛所有),配置为false则可根据不同URL进行链路的限流操作。
3、Spring Cloud Alibaba 在2.1.1.RELEASE版本后,可以根据配置spring.cloud.sentinel.filter.enabled: false来关闭自动收敛。


如何进行测试呢?
1、修改父pom中的Spring Cloud Alibaba 的依赖版本信息

<!-- 将2.1.0版本更改为2.1.1版本 -->
<spring.cloud.alibaba.version>2.1.1.RELEASE</spring.cloud.alibaba.version>

 

2、增加一个服务接口,使得两个controller均可调用。

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

@Service
public class ServiceImpl {

    //必须加上 @SentinelResource 注解,此处该注解类似 @HystrixCommand
    @SentinelResource("message")
    public  String message(){
        return "message";
    }
}

3、编写配置类文件,设置WEB_CONTEXT_UNIFYfalse

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 registrationBean = new FilterRegistrationBean();
        registrationBean.setFilter(new CommonFilter());
        registrationBean.addUrlPatterns("/*");
        //入口资源关闭聚合
        registrationBean.addInitParameter(CommonFilter.WEB_CONTEXT_UNIFY,"false");
        registrationBean.setName("sentinelFilter");
        registrationBean.setOrder(1);
        return registrationBean;
    }
}

4、在yml配置文件中,需要新增配置信息
在这里插入图片描述
5、编写请求控制器类,调用服务中的方法。

import cn.linkpower.servive.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController {

    /**
     *链路demo
     */

    @Autowired
    private ServiceImpl serviceImpl;

    @RequestMapping("/message1")
    private String message1(){
        serviceImpl.message();
        return "lianlu  message1";
    }

    @RequestMapping("/message2")
    private String message2(){
        serviceImpl.message();
        return "lianlu  message2";
    }
}

6、启动并测试

先分别请求 http://localhost:8500/message1 和 http://localhost:8500/message2 使得Sentinel中存在监控信息。

设置Sentinel中的 message信息。采取链路形式构成关联
在这里插入图片描述

再次快速请求 http://localhost:8500/message1 和 http://localhost:8500/message2
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

[总结:]

当配置message资源 链路 /message1 请求接口时,如果 /message1 出现请求超过限流值,则会触发限流,但 /message2 并不受影响!
反之,/message2 受影响,但 /message1不受影响!

[注:]@SentinelResource 注解在博客下会说明!

四、Sentinel 流控效果

此处的效果测试,均采用 阈值类型:QPS流控模式:直接

4.1、直接

直接失败,抛出异常,不做任何额外处理,是最简单的方式。

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

4.2、Warm Up

从开始阈值,到最大QPS阈值会有一个缓冲阶段,
一开始的阈值是最大QPS阈值的1/3,然后缓慢增长,直到最大阈值,适用于突然增大的流量转化为缓步增长。
避免突然大流量造成服务器的宕机!

在这里插入图片描述

阈值最初为10;
最初的处理请求数最大为:10/3=3;
在5s时间内,由3缓慢升为10。

使用jmeter进行压测
创建线程组:
在这里插入图片描述
创建请求:
在这里插入图片描述
在这里插入图片描述

突然出现大量请求,不会直接进行实际处理,会将请求预热后在做处理

4.3、排队等待

让请求以均匀的速率通过,单机阈值为每秒通过的请求数,其余的排队等待;
其次,还可以设置一个排队等待的超时时间,若请求在超时时间内还未被处理,则会被丢弃。

在这里插入图片描述

达到的目的:
匀速处理多个请求,而不是一开始超过阈值的请求直接失败!

编写测试接口:

   /**
     * 队列等待模式测试
     */
    @RequestMapping("/test4")
    public String test4(){
        log.info("当前线程执行信息:{}",Thread.currentThread().getName());
        return "duilie wait test4";
    }

 

在这里插入图片描述
设置 Jmeter 一个线程每秒钟访问俩次:
在这里插入图片描述
在这里插入图片描述
打印日志信息:
在这里插入图片描述

观察发现:
每秒钟限定处理一个请求数。
但是jmeter每秒钟发送2个请求。
设置了延迟等待 500ms后,只有少数请求会进入降级!

五、Sentinel熔断降级

在这里插入图片描述

5.1、RT 平均响应时间

1、如果请求的平均响应数超过阈值(ms),则会进入准降级状态
2、如果接下来1s内持续进入5个请求,他们的RT持续超过了这个阈值,那么在接下来的时间窗口(s)内,就会对这个服务进行降级
3、RT默认最大为4900ms,如果需要更大,可以通过 -Dcsp.sentinel.statistic.max.rt=xxx 进行配置。

在这里插入图片描述
配置案例:
java代码逻辑为:

   /**
     * 降级测试
     * @param name
     * @return
     */
    @RequestMapping("/jiangji")
    public String jiangji(@RequestParam("name") String name){
        //当请求参数为 1 时,响应延迟600ms 也就是RT可以配置允许时间比这个数低的值
        if("1".equalsIgnoreCase(name)){
            try {
                Thread.sleep(600);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        log.info("请求的name:{},时间为:{}",String.valueOf(name),new Date().getTime());
        return "jiangji test name="+String.valueOf(name)+" 当前时间:"+new Date().getTime();
    }

 

先进行请求,然后sentinel中配置图如下:
在这里插入图片描述
在这里插入图片描述
请求测试:

1、正常请求:
http://localhost:8500/jiangji?name=2
不会出现熔断保护。
2、异常请求:
http://localhost:8500/jiangji?name=1在这里插入图片描述
在这里插入图片描述
熔断保护时间内,请求正常流程:
http://localhost:8500/jiangji?name=11
在这里插入图片描述
保护时间过后,在请求正常流程:
http://localhost:8500/jiangji?name=11
在这里插入图片描述
在这里插入图片描述

[总结]

1、配置熔断保护的接口,如果不出现超时情况时,不会触发熔断保护降级。
2、当设定RT为500ms后,请求异常流程,1s内平均请求响应都超时并达到对应的数目(测试显示5个),会触发熔断保护,并保护10s(这个时间是时间窗口的配置)。
3、熔断保护期间内,正常请求也会被熔断、降级。
4、10s后,熔断结束,会重新对请求响应时间进行统计判断。

5.2、异常比例数

每秒的异常总数,占通过量的比值超过配置的值之后,触发熔断降级。
时间窗口和之前一样,属于熔断保护时间。
占的比值数范围为:[0.0,1.0];

代码案例:

    /**
     * 异常触发熔断降级测试
     */
    int a = 0;
    @RequestMapping("/exct")
    public String exct(){
        a ++ ;
        if(a % 3 == 0){
            //模拟异常
            throw new RuntimeException("请求取余数为0了");
        }
        return "异常导致的熔断降级测试";
    }

 

暂时未配置时,当请求数每次达到 a % 3 == 0时,就会产生异常:

http://localhost:8500/exct
在这里插入图片描述

配置Sentinel,使得其具备熔断降级的策略:
在这里插入图片描述

由于 a % 3 == 0触发异常,也就是说异常比例为 1/3。只需要配置的数小于 1/3即可。

在这里插入图片描述
请求测试:

http://localhost:8500/exct
正常缓慢请求时,依然和之前一致,出现报错信息。
当请求异常比例大于等于配置数时,出现熔断降级。
在这里插入图片描述
在这里插入图片描述

5.3、异常数

资源 1分钟 内的异常总数超过限定的阈值,触发熔断降级!

在这里插入图片描述

设定异常数为3,表示一分钟请求的异常出现了3个及以上,触发熔断降级!

[注意]此处有坑!

由于异常数是按照分钟统计的个数,时间窗口中的设置也必须要大于60s
不然会出现:结束熔断保护后仍可能继续熔断保护(不会释放!)

请求测试:

http://localhost:8500/exct
当请求出现异常的次数达到设定的值时,立马出现熔断降级现象。
在这里插入图片描述
当熔断保护的时间过了之后,释放,再次请求会重新进行统计!
在这里插入图片描述

六、Sentinel热点规则

热点参数流控规则。

何为热点:

热点即经常访问的数据。

热点限流的思想是什么?

假设某一时间段内的某个用户频繁的去访问,就可以采取热点规则方式,对其进行限流操作。

6.1、初级配置和测试

案例测试:

 /**
     * 热点规则测试项
     * @param p1
     * @param p2
     * @return
     */
    @RequestMapping("/hostkey")
    //名称唯一 但 热点规则 必须需要此项配置,无此注解不生效
    @SentinelResource(value = "hostkey",blockHandler = "fallback_hostkey")
    public String testHotKey(@RequestParam(value="p1",required = false) String p1,
                             @RequestParam(value="p2",required = false) String p2){

        return "---- test Hot Key ----";
    }
    // 修改sentinel 降级的默认回执方法(传递参数的一致性,并且需要携带 BlockException)
    public String fallback_hostkey(String p1, String p2, BlockException blockException){
        return "限流咯。。。。";
    }

当不配置任何规则时,此时的回执信息为:

http://localhost:8500/hostkey
在这里插入图片描述

配置Sentinel中的热点规则属性。
在这里插入图片描述

当请求地址携带p1参数,且每秒钟的请求数高于配置的1次时,触发降级。

请求测试:

1、不携带参数,快速点击
http://localhost:8500/hostkey
在这里插入图片描述
2、携带参数,但不携带p1,快速点击
http://localhost:8500/hostkey?p2=33333
在这里插入图片描述
3、携带p1参数,缓慢点击
http://localhost:8500/hostkey?p1=33333
在这里插入图片描述
4、携带p1参数,快速点击
在这里插入图片描述

6.2、高级配置

针对个别用户频繁访问时,采取了限流操作(按照参数接受类型,但不是具体的数值)。
但是,针对管理员频繁的访问查看或测试数据时,此时不应限流。

配置项:

达到的目的,当p1为520时,限流量放大!

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

请求测试:

1、缓慢请求,p1非特定值
http://localhost:8500/hostkey?p1=52
在这里插入图片描述
2、快速请求,p1非特定值
在这里插入图片描述
3、缓慢请求,p1为特定值
http://localhost:8500/hostkey?p1=520
在这里插入图片描述
4、快速请求,p1为特定值(每秒请求大于2触发)
在这里插入图片描述

6.3、@SentinelResource 修饰的controller出现异常了会走blockHandler提示返回么?

修改controller,如下所示:

 // 修改sentinel 降级的默认回执方法
    public String fallback_hostkey(String p1, String p2, BlockException blockException){
        return "限流咯。。。。";
    }

    /**
     * 热点规则测试项
     * @param p1
     * @param p2
     * @return
     */
    @RequestMapping("/hostkey2")
    //名称唯一 但 热点规则 必须需要此项配置,无此注解不生效
    @SentinelResource(value = "hostkey",blockHandler = "fallback_hostkey")
    public String testHotKey2(@RequestParam(value="p1",required = false) String p1,
                             @RequestParam(value="p2",required = false) String p2){
        int a = 10/0;
        return "---- test Hot Key ----";
    }

重启项目,再次访问:

http://localhost:8500/hostkey2
在这里插入图片描述

[发现:]

出现了异常,但未进入blockHandler中。

[如何解决呢?]

@SentinelResource 其实和 @HystrixCommand 类似,拥有一个 fallback!

修改代码:

   // 修改sentinel 降级的默认回执方法
    public String fallback_hostkey(String p1, String p2, BlockException blockException){
        return "限流咯。。。。";
    }

    /**
     * 热点规则测试项
     * @param p1
     * @param p2
     * @return
     */
    @RequestMapping("/hostkey2")
    //名称唯一 但 热点规则 必须需要此项配置,无此注解不生效
    @SentinelResource(value = "hostkey",blockHandler = "fallback_hostkey")
    public String testHotKey2(@RequestParam(value="p1",required = false) String p1,
                             @RequestParam(value="p2",required = false) String p2){
        int a = 10/0;
        return "---- test Hot Key ----";
    }

重启再次请求:

http://localhost:8500/hostkey2
在这里插入图片描述

七、Sentinel系统自适应限流

之前的配置操作,采取的是针对单个请求地址请求别名进行配置的限流操作,sentinel同时也提供了一种很潮流的方式实现配置操作—系统自适应限流

何为系统自适应限流?

Sentinel 系统自适应限流从整体维度对应用入口流量进行控制,结合应用的 LoadCPU 使用率总体平均 RT入口 QPS并发线程数等几个维度的监控指标,通过自适应的流控策略,让系统的入口流量系统的负载达到一个平衡,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。

系统自适应限流

文档中,对系统自适应限流有如下几种配置:
在这里插入图片描述
阈值类型的含义如下所示:

配置案例:
配置入口QPS
在这里插入图片描述

只配置 QPS 项,其他流控模式未配置。

请求测试:
缓慢请求 /test1
在这里插入图片描述
快速请求 /test1
在这里插入图片描述
缓慢请求 /test2
在这里插入图片描述
快速请求 /test2
在这里插入图片描述

八、代码git地址


git地址

以上就是所有内容,学了sentinel的都会对这篇文章赞不绝口的。

----我是“道祖且长”,一个在互联网“苟且偷生”的Java程序员

标签:8500,String,阈值,熔断,Sentinel,限流,sentinel,请求
来源: https://blog.csdn.net/yuanchangliang/article/details/111663821