22-07-24 SpringCloud(04) Sentinel、流控模式与流控效果、降级熔断策略、热点key限流

发布于:2023-02-15 ⋅ 阅读:(892) ⋅ 点赞:(0)

和珅有宋朝时期的汝窑三足笔洗,这俩件是举世罕见的宝贝,全天下也找不到第三只,当时这一对就花了一万两银子。但是和珅得手后,却立马砸碎了一只,这样全天下就只剩下一只了,剩下那只的价值立刻翻了10倍! 


SpringCloud Alibaba Sentinel:也被称为分布式系统的流量防卫兵 

随着微服务的流行,服务和服务之间的稳定性变得越来越重要。

Sentinel以流量为切入点,熊流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性【流量就是客户端请求】

Sentinel 的历史:

- 2012 年,Sentinel 诞生,主要功能为入口流量控制。

- 2013-2017 年,Sentinel 在阿里巴巴集团内部迅速发展,成为基础技术模块,覆盖了所有的核心场景。Sentinel 也因此积累了大量的流量归整场景以及生产实践。

- 2018 年,Sentinel 开源,并持续演进。

- 2019 年,Sentinel 朝着多语言扩展的方向不断探索,推出 C++ 原生版本,同时针对 Service Mesh 场景也推出了 Envoy 集群流量控制支持,以解决 Service Mesh 架构下多语言限流的问题。

- 2020 年,推出 Sentinel Go 版本,继续朝着云原生方向演进。

Sentinel 分为两个部分:

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

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

sentinel官网:GitHub - alibaba/Sentinel: A powerful flow control component enabling reliability, resilience and monitoring for microservices. (面向云原生微服务的高可用流控防护组件)


安装运行Sentinel

1、Sentinel控制台

下载jar包

保存的地方不能有中文和空格(我这次就有中文,吃过一次亏了。。。。)

下载地址: Releases · alibaba/Sentinel · GitHub

让jar包运行起来

sentinel控制台,默认端口号是8080

如果想指定端口:

在小黑窗中执行:java -Dserver.port=8088 -jar sentinel-dashboard-1.8.1.jar

访问Sentinel控制台

 Sentinel启动后,访问http://localhost:8080/,登录账号密码均为sentinel

登录成功页面,此时页面为空,因为还没有监控任何服务。sentinel是懒加载的,如果服务没有被访问,看不到该服务信息。


2、Sentinel入门案例

创建工程  cloudalibaba-sentinel-service8401

1、核心依赖

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-datasource-nacos</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>

2.application.yml配置文件

8719这个端口的作用

server:
  port: 8401

spring:
  application:
    name: cloudalibaba-sentinel-service
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
    sentinel:
      transport:
        dashboard: localhost:8080
        port: 8719  #默认8719,应用与Sentinel控制台交互的端口,应用本地会起一个该端口占用HttpServer

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

3、主启动

4、controller层写点东西,好测试

@RestController
@Slf4j
public class FlowLimitController{
    @GetMapping("/testA")
    public String testA() {
        return "------testA";
    }

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

测试

先启动本地的nacos,怎么启动看我上一篇文章,不再多说  22-07-24 西安 SpringCloud(03) SpringCloud alibaba、Nacos、CAP和Base_£小羽毛的博客-CSDN博客

再启动该工程 :cloudalibaba-sentinel-service8401

1、查看Sentinel控制台,空空如也,因为Sentinel是懒加载

查看nacos控制台,不出所料

 2、执行访问

再查看Sentinel控制台,就有了


Sentinel流控规则

1、QPS 每秒查询率

通常使用QPS衡量一个接口的性能(处理能力)

一台服务器 每秒能够相应的查询次数,是对一个特定的查询服务器 在规定时间内 所处理流量多少的衡量标准, 即每秒的响应请求数,也即是最大吞吐能力。

当 QPS 超过某个阈值时,采取措施 流量控制。流量控制的效果包括以下几种:  直接拒绝、Warm Up、匀速排队。


2、三种流控模式

流控模式分3种:直接、关联,链路

直接 快速失败   默认的流量控制方式

1.资源名目前呢是请求路径,一会就不这么用了,会改为资源名。现在是针对某一个请求

2.先演示最简单的“直接 快速失败”(达到限流条件时,直接抛出异常)

3.测试演示

QPS单机阈值为1表示:1秒钟内查询1次就是OK,若超过次数1,就直接-快速失败,报默认错误

关联-快速失败

当关联资源/testB的QPS阀值超过1时,就限流/testA的REST访问地址

挺考验手速,不过对我而言还不是轻而易举


3、postman里新建多线程集合组【不推荐】

当然,要是你手速不够,我们可以借助与postman。推荐使用jmeter

22-07-22 西安 SpringCloud(02) Hystrix断路器、jmeter并发测试、Gateway网关、分布式链路请求跟踪_£小羽毛的博客-CSDN博客

postman里新建多线程集合组,将请求保存到集合组

1、qq

2、运行线程集合组

 3、在弹出的新窗口设置并发访问参数

 这个期间去访问必然是这种结果


链路

只记录指定链路上的流量,指定资源从入口资源进来的流量达到阈值,就进行限流


4、三种流控效果

快速失败

上面演示都用的流控效果  “快速失败”,当QPS超过任意规则的阈值后,新的请求就会被立即拒绝,拒绝方式为抛出FlowException

直接失败,抛出异常:Blocked by Sentinel (flow limiting)


预热 Warm Up

预热/冷启动方式。

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

阈值除以coldFactor(coldFactor默认值为3),经过预热时长后才会达到阈值

系统初始化的阈值为10/3约等于3,即阈值刚开始为3;然后过了5秒后阈值才慢慢升高,恢复到10【意思是5秒内阈值慢慢到达10】

测试:刚开始的时候,你只要满足了QPS大于3是可以触发快速失败那个页面的。5秒后阈值就到10了,我这手速是快,但是浏览器跟不上啊

应用场景:

秒杀系统 在开启的瞬间,会有很多流量上来,很有可能把系统打死,预热方式就是为了保护系统,可慢慢的把流量放进来,慢慢的把阈值增长到设置的阈值。


排队等待

匀速排队,让请求以均匀的速度通过,阈值类型必须设置成QPS,否则无效。对应漏桶算法

/testB每秒1次请求,超过的话就排队等待,等待的超时时间为20000毫秒

测试:点多了会打圈。表示等待。不再报“快速失败那个异常页面了”


Sentinel降级、熔断策略

慢调用比例、异常比例 、异常数

1、慢调用比例

在testA方法中线程睡眠0.3秒

    @GetMapping("/testA")
    public String testA() {
        try {
            Thread.sleep(300);
            
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "------testA";
    }

在sentinel控制台新增熔断规则如下:

当然,我没测出来。种种原因吧,连老师上课也是又不少测不出来


2、异常比例

在testA方法中手写一个异常

    @GetMapping("/testA")
    public String testA() {
        int num=10/0;
        return "------testA";
    }

在sentinel控制台修改熔断规则如下 

1.发送请求,这是没有熔断之前的访问效果

2.这是触发熔断条件,熔断之后的显示


3、异常数

在sentinel控制台修改熔断规则如下 

触发熔断后


热点key限流

1、@SentinelResource

之前限流出问题后,都是用sentinel系统默认的提示:Blocked by Sentinel(flow limiting)

现在使用@SentinelResource在方法出现问题后,可以找到对应的兜底方法

官网:热点参数限流 · alibaba/Sentinel Wiki · GitHub

@SentinelResource

其实在“尚医通项目-预约挂号”中,就应用到了热点key限流

热门医院 的号可能很紧张,尤其是放号的那一刻,可能有很多用户抢号,那么如何保证服务正常运行呢,因此我们需要对热门医院做流量控制,阿里 Sentinel流量控制 工具就能很好的解决我们的问题,它能根据热点值,动态控制流量。 


2、热点key使用

1.新增控制器方法

简单来说,@SentinelResource注解中的俩个属性作用

value=资源名(注意资源名不要重复)

blockHandler:不管是热点限流还是非热点限流,只要该接口限流,就会是调用该属性所声明的方法

兜底方法deal_testHotKey()  参数要和接口方法的参数一致(包括),还要有一个必要参数BlockException e

    @GetMapping("/testHotKey")
    //value 资源名,配置热点key。违法配置规则则,走blockHandler降级方法
    @SentinelResource(value = "testHotKey",blockHandler = "deal_testHotKey")
    public String testHotKey(String p1, String p2) {
        return "------testHotKey";
    }

    //兜底方法
    // BlockException exception 必须得有
    public String deal_testHotKey (String p1, String p2, BlockException exception){
        return "------deal_testHotKey,o(╥﹏╥)o";
    }

 2.配置热点规则

资源名怎么设置?

如果你的接口,路径只有一段,可以直接使用路径作为资源名

如果路径有多段,不建议使用路径作为资源名

3.测试

3.1 先不使用热点key “p1”,点击测试 

 3.2一旦有了热点key "p1"的参与。且给我们返回的界面是我们自己定义的,再也不是那个丑不拉几的玩意


用着用着,让我测出来一个bug,我服了

这种方式传递参数,p1,p2是必传的,那个pathVarible中的required一点用没真是


1、不传参数测试 /test/testHotKey

2、传参数,但不传p1,只传p2  /test/testHotKey/?p2=1

3、传参数,带了p1,p2有没有根本不影响  /test/testHotKey/?p1=1


3、热点key- 参数例外项

热点参数的注意点,参数必须是基本类型或者String

修改热点key的配置

老师说:热点限流阈值一般要小于非热点限流阈值,目前还是理解不了、、、 

当参数不包含p1,多少个请求也不会走降级处理方法。

测试当参数中包含p1的时候:

  • 且当p1等于10000的时候,阈值变为3

/test/testHotKey/?p1=10000

  • 且当p1不等于10000的时候,阈值就是平常的5

/test/testHotKey/?p1=1    下面口误了,是只有第6个走了降级处理

1、其它的规则也可以使用资源名控制规则(也可以使用路径控制)此时如果违反规则使用BLockHandler进行降级处理

2.其它的规则也可以使用路径控制规则:如果违反了规则使用默认的降级处理方案

value = ""  用于设置资源名称,只有根据资源名称设置的规则,才能执行blockHandler所引用降级方法

方法内部错误
方法内容异常不能使用那BLockHandler进行降级,但是有专门的方法错误降级方法,会加一个fallback属性

3.BLockHandler和fallback俩个可以同时存在

则违反规则走违反规则处理,没违反规则走异常处理

测试:

3.1.修改代码,使testHotKey资源对应的方法有异常

    @GetMapping("/testHotKey")
    //value 资源名,配置热点key。违法配置规则则,走blockHandler降级方法
    @SentinelResource(value = "testHotKey",blockHandler = "deal_testHotKey",fallback = "handleException2")
    public String testHotKey(@RequestParam(value = "p1",required = false) String p1,
                             @RequestParam(value = "p2",required = false) String p2) {
        int age = 10/0;
        return "------testHotKey";
    }

    //兜底方法
    // BlockException exception 必须得有
    public String deal_testHotKey (String p1, String p2, BlockException exception){
        return "------deal_testHotKey,o(╥﹏╥)o";
    }

    public String handleException2(@RequestParam(value = "p1",required = false) String p1,
                             @RequestParam(value = "p2",required = false) String p2,Throwable throwable) {
        //方法参数列表和原函数一致或者可以额外多一个Throwable用于接收对应的异常
        return "-----handleException2异常处理--噜啦啦";
    }

3.2

 3.3


系统规则


规则持久化

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

无论是通过硬编码方式来更新规则,还是通过接入 Sentinel Dashboard 后,在页面上操作更新规则,都无法避免一个问题,那就是服务重新后,规则就丢失了,因为默认情况下规则是保存在内存中的。sentinel重启,配置规则也会消失

我们在 Dashboard 上为客户端配置好了规则,并推送给了客户端。这时由于一些因素客户端出现异常,服务不可用了,当客户端恢复正常再次连接上 Dashboard 后,这时所有的规则都丢失了,我们还需要重新配置一遍规则,这肯定不是我们想要的。

1.使用nacos入库(实际中不会用)

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

引入依赖

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

修改配置文件

这里datasource后的d1是数据源名称,可以随便写,推荐使用服务名

rule-type 配置的是规则类型
#authority(授权规则)、degrade(降级规则)、flow(流控规则)、
#param(热点规则)、system(系统规则)五种规则持久化到Nacos中
 

在尚医通项目中,dataId是这么配置的,下面会用到,一致就好。我觉着还是用服务名好

spring.cloud.sentinel.datasource.consumer.nacos.dataId
=${spring.application.name}-sentinel-rules

spring.cloud.sentinel.datasource.consumer.nacos.groupId
=SENTINEL_GROUP

2、在nacos控制台创建流控规则

Nacos业务规则配置

 json文件 中对应在sentinel的可视化配置

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

其中补充俩点:

流控模式,0-直接,1-关联, 2-链路

流控效果。0-快速失败,1-warm up 2-排队等待

3.重新启动服务,测试nacos中配置的流控规则是否生效

启动服务,在浏览器得先访问一下 http://localhost:8207/test/testHotKey

在流控规则中就有了我们刚刚配置在nacos中的配置                


网站公告

今日签到

点亮在社区的每一天
去签到