Sentinel:服务限流

创建工程测试工程

1.导入依赖

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

<dependencyManagement>
    <dependencies>
        <!-- spring cloud 总体依赖版本管理 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Hoxton.SR12</version>
            <scope>import</scope>
            <type>pom</type>
        </dependency>
        <!-- spring cloud alibaba 总体依赖版本管理 -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-dependencies</artifactId>
            <version>2.2.7.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<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>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
    </dependency>
</dependencies>

2.yml配置

server:
  port: 9000
spring:
  application:
    name: nacos-sentinel
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.8.128:8848
    sentinel: # 配置sentinel信息
      transport:
        dashboard: 192.168.8.128:8858 # 配置sentinel服务器地址,客户端连接sentinel
        port: 8719 # 代表sentinel客户端和控制台通信的端口,默认为8719,sentinel监控客户端

4.创建控制器

@RestController	
public class SentinelController {
    
    
    @RequestMapping("/fs")
    public String show(){
    
    
        return "hello world!";
    }
}

访问: http://localhost:9000/fs
在这里插入图片描述

流控

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

1.资源名: 标识资源的唯一名称,默认为请求路径,也可以在客户端中使用@SentinelResource配置。
2.针对来源: Sentinel可以针对服务调用者进行限流,填写微服务名称即spring.application.name,默认为default,不区分来源。
3.阈值类型:
QPS(每秒钟的请求数量): 当调用该api的QPS达到阈值的时候,进行限流。
线程数: 当调用该api的线程数达到阈值的时候,进行限流。
4.单机阈值: 定义QPS或线程数的具体控制阈值。
5.是否集群: 默认不集群。
6.流控模式:
直接: 当api调用达到限流条件的时,直接限流。
关联: 当关联的资源请求达到阈值的时候,限流自己,例: 设置/aa和/bb,在/bb的关联中填入/aa,/aa在1s被访问5次(假设限制)则限流/bb
链路: 只记录指定链路上的流量(指定资源从入口资源进来的流量,如果达到阈值,则进行限流),例: 从指定/aa下访问/fs的请求才统计限流
7 流控效果:
快速失败: 直接失败。
Warm Up(预热): 设置预热时长,在预热时长内,处理请求上线为 请求数/预热时长,预热时长过后,恢复原单机阈值
排队等待: 匀速排队,让请求匀速通过,阈值类型必须设置为QPS,否则无效。

熔断

在这里插入图片描述

下图表示访问/fs控制单元的5次请求内,有50%的请求的响应时长超过100ms,则熔断3秒,熔断期间直接降级
在这里插入图片描述
熔断策略:
1 慢调用比例: 按照响应时间进行判断,比例,数量进行判断。
2.异常比例: 按照异常比例进行判断。
3 异常数量: 按照异常的数量进行判断。

最大RT: 响应时间,单位毫秒。指请求及响应的时间。最大RT :300,表示如果请求及响应时间超过300毫秒则为慢调用。
比例阈值: 取值[0.0-1.0],0表示0%,1.0表示100%。表示慢调用出现的比例。
熔断时长: 当满足熔断条件后,熔断时间。
最小请求数: 进行判断的最小请求的数量。

热点

简单说: 就是更具请求携带的不同的参数值,来采取不同的限制.
添加控制层代码: 在方法前加@SentinelResource(value = “firstResource(随意指定)”)
注意 热点 只能在 @SentinelResource该注解指定的名称中添加,不能直接添加到对应的控制单元上
在这里插入图片描述

@RestController
public class DemoController {
    
    
    @RequestMapping("/fs")
    @SentinelResource(value = "firstResource")
    public String show(String name){
    
    
        System.out.println(name);
        return "hello world!";
    }
}

下图就是在请求参数不为aa时,一秒内超过2个请求就降级,请求参数为aa时,一秒内超过5个请求就降级才降级
在这里插入图片描述
参数索引: 请求传入的参数索引,从0开始计数。即控制器方法参数表中的热点参数索引。
单机阈值: 与流控规则中的单机阈值含义相同。
统计窗口时长: 对单机阈值的流控限制统计窗口时长。如:单机阈值 3, 统计窗口时长 1 ,则1秒内QPS阈值为3。
设置热点参数: 当创建热点规则后,会在Sentinel Dashboard中热点规则中出现我们建立的规则。

在热点规则中点击编辑
参数类型: 热点参数数据类型。
参数值: 热点参数具体值。
限流阈: 当请求参数值与热点参数值相同时的QPS阈值。
添加按钮: 当设置好热点参数例外项后,一定要点击添加按钮,否则热点参数不生效

授权规则

就是让那些ip和访问,哪些ip不能访问

使用授权规则,必须在被Sentinel管理的应用这增加解析类型,根据IP实现授权规则限制

/**
 * 自定义解析器。用于配合Sentinel实现授权管理的。
 * 要求当前类型的对象,必须被spring容器管理。
 *
 * RequestOriginParser - 用于解析每个请求的解析器。
 *  可以获取客户端IP地址。
 */
@Component
public class MyParser implements RequestOriginParser {
    
    
    /**
     * 接口中定义的唯一解析方法。用于解析请求对象的。
     * @param httpServletRequest
     * @return 解析后的结果。一般是客户端IP地址。
     */
    @Override
    public String parseOrigin(HttpServletRequest httpServletRequest) {
    
    
        System.out.println("remoteAddr = " + remoteAddr);
        System.out.println("remoteHost = " + httpServletRequest.getRemoteHost());
        System.out.println("remotePort = " + httpServletRequest.getRemotePort());

        return httpServletRequest.getRemoteAddr();
    }
}

在这里插入图片描述
表示只有127.0.0.1才能访问该地址
在这里插入图片描述
1.流控应用: 具体访问这个资源的客户端,即客户端IP地址。多个地址使用逗号 ‘,’ 分隔。
2 授权类型: 即流控应用是否可访问当前被授权规则管理的资源。

  • 白名单:可以访问。
  • 黑名单:不可访问。

系统规则

在这里插入图片描述

系统规则是对整个系统进行设置的规则。阈值类型包含以下五种:
​1.Load: 自适应(仅对 Linux/Unix-like 机器生效),系统的 load 作为启发指标,进行自适应系统保护。当系统 load超过设定的启发值,且系统当前的并发线程数超过估算的系统容量时才会触发系统保护(BBR 阶段)。系统容量由系统的 maxQps minRt 估算得出。设定参考值一般是 CPU cores 2.5。
2.CPU使用率: 当系统 CPU 使用率超过阈值即触发系统保护(取值范围 0.0-1.0),比较灵敏。
3.RT平均 RT,当单台机器上所有入口流量的平均 RT 达到阈值即触发系统保护,单位是毫秒。
4.线程数: 并发线程数,当单台机器上所有入口流量的并发线程数达到阈值即触发系统保护。
5.QPS: 入口 QPS,当单台机器上所有入口流量的 QPS 达到阈值即触发系统保护。

@SentinelResource

利用这个注解可以自定义降级和发生异常时调用的方法
1.fallback回退: 在标注了@SentinelResouce注解的方法,发生了Java异常时的回退处理。
2.block回退: @SentinelResource资源访问不符合Sentinel控制台定义的规则时的回退。当没有定义Block回退时默认为Blocked by Sentinel (flow limiting)

 *  fallback - 是当前服务逻辑,发生异常的时候,Sentinel辅助回调的降级方法名称。
 *   当方法抛出异常。触发fallback配置的方法,返回给客户端降级数据。
 *   没有默认值。
 *   方法定义要求:
 *    1. fallback方法签名和当前方法签名,除方法名称外其他都一致。

 *  blockHandler - 是当前服务逻辑,触发Sentinel限制阈值时,Sentinel辅助回调的降级方法名。
 *   当某限制规则被触发,blockHandler配置的方法运行,返回给客户端降级数据。
 *   没有默认值。
 *   方法定义要求:
 *    1. blockHandler方法签名和当前方法签名,除方法名称和参数表外,都一致。
 *    2. 参数表要求:包含当前方法所有参数,在参数表最后,增加BlockException参数。

 *   BlockException是Sentinel定义的规则异常顶级父类。有若干子类型。
 *       异常参数对象的具体类型,代表触发了Sentinel约束的哪一种规则。
 *        FlowException - 流控规则
 *        ParamFlowException - 热点规则
 *        DegradeException - 降级规则
 *        AuthorityException - 授权规则
 *        SystemBlockException - 系统规则
@RestController
public class DemoController {
    
    
    @GetMapping("/sayHello")
    @SentinelResource(value = "firstResource", fallback = "sayHelloFallback", blockHandler = "sayHelloBlockHandler")
    public String sayHello(String name){
    
    
        System.out.println("sentinel name = " + name);
        // 用于测试异常处理
        if(name.equals("exception")){
    
    
            throw new RuntimeException("测试异常处理");
        }
        return "您好:" + name;
    }
    public String sayHelloFallback(String name){
    
    
        System.out.println("sayHelloFallback方法运行,参数是:" + name);
        return "服务器忙,请稍后重试!";
    }
    public String sayHelloBlockHandler(String name, BlockException ex){
    
    
        if(ex.getClass() == FlowException.class){
    
    
            System.out.println("流控规则");
            return "参与活动人数太多,请稍后重试!";
        }
        if(ex.getClass() == ParamFlowException.class){
    
    
            System.out.println("热点规则");
            return "查询的数据不存在!";
        }
        if(ex.getClass() == DegradeException.class){
    
    
            System.out.println("降级规则");
            return "服务器爆炸!";
        }
        if(ex.getClass() == AuthorityException.class){
    
    
            System.out.println("授权规则");
            return "您的权限不足,请联系管理员!";
        }
        if(ex.getClass() == SystemBlockException.class){
    
    
            System.out.println("系统规则");
            return "您访问的网站已下线,明天再来吧!";
        }
        System.out.println("其他问题");
        return "未知原因";
    }
}

配置持久化

Sentinel中各种流量控制可以借助持久化工具进行存储。示例中利用:Nacos配置中心存储相关配置。
1.在nocos中新增配置
在这里插入图片描述
2.配置内容:

[
{
    
    
"resource": "/demo01",
"limitApp": "default",
"grade": 1,
"count": 3,
"strategy": 0,
"controlBehavior": 0,
"clusterMode": false
}
]

配置详解:

  • resource:资源名,即限流规则的作用对象
  • limitApp:流控针对的调用来源,若为 default 则不区分调用来源
  • grade:限流阈值类型(QPS 或并发线程数);0代表根据并发线程数量来限流,1代表根据QPS来进行流量控制
  • count:限流阈值
  • strategy:流控模式,调用关系限流策略(0-直连,1-关联,2-链路)
  • controlBehavior:流量控制效果(0-快速失败、1-Warm Up、2-排队等待)
  • clusterMode:是否为集群模式

3.导入依赖:

        <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>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-datasource-nacos</artifactId>
        </dependency>

4.yml配置

server:
  port: 8080
spring:
  application:
    name: nacos-sentinel
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
    sentinel: # 配置sentinel信息
      transport:
        dashboard: 127.0.0.1:8858 # 配置sentinel服务器地址。
        port: 8719 # 代表sentinel客户端和控制台通信的端口,默认为8719
      datasource: # 配置sentinel规则存储的数据源
        ds: # 定义数据源的key
          nacos: # 指定nacos作为数据源
            server-addr: 127.0.0.1:8848 # nacos服务器地址
            data-id: hello  # nacos中配置文件名称
            group-id: world # nacos中配置文件所属分组, 默认DEFAULT_GROUP
            data-type: json # nacos中配置文件类型, 默认json
            rule-type: flow # nacos中配置文件定义的规则类型。

5.重启后,访问 http://localhost:9000/fs?name=test在不做任何规则配置的前提下,查看Sentinel控制台中的流控规则面板,查看是否存在流控规则信息。
存在!

执行流程

1.微服务启动
2.根据配置文件application.yml中的配置,动态访问Sentinel Datasource,读取持久化规则配置3.sentinel客户端占用端口8719,连接sentinel服务器(端口是8858)
4.如果有持久化的规则配置,在连接sentinel服务器的同时,提交持久化规则配置内容5.客户端浏览器请求微服务
6.微服务中的sentinel客户端拦截请求,上报请求信息到sentinel服务器(端口8858)
7.sentinel服务器检测已配置的规则限制(如:流控、降级、热点等)
8.sentinel服务器返回规则限制是否被触发(返回到sentinel客户端,端口是8719)
9.如果流控规则已触发,sentinel客户端直接返回降级(Blocked by sentinel),或调用SentinelResource注解配置的blockHandler返回托底数据。
10.如果流控规则未触发,微服务正常执行,并返回运行结果给客户端。|

猜你喜欢

转载自blog.csdn.net/m0_56182317/article/details/130336736