整个项目请看gitee:https://gitee.com/xwb1056481167/spring-cloud

sentinel的安装和项目集成:https://blog.csdn.net/www1056481167/article/details/113679945

流控规则

  • 资源名: 唯一名称,默认请求路径
  • 针对来源: Sentinel可以战队调用者进行限流,填写服务名。默认为default(不区分来源)
  • 阈值类型/单击阈值
    • QPS(每秒中的请求数量): 当调用该api的QPS达到阈值的时候,进行限流
    • 线程数: 当调用该api的线程数达到阈值的时候,进行限流
  • 是否集群: 不需要集群
  • 流控模式:
    • 直连: api达到限流条件时,直接限流
    • 关联: 当关联的资源达到阈值的时候,就限流自己
    • 链路: 指记录指定链路上的流量(指定资源从入口资源进来的流量,如果达到阈值,如果达到阈值,就进行限流)【api级别的针对来源】
  • 流控效果:
    • 快速失败: 直接失败,抛异常 + Warm Up: 根据codeFactor(冷加载因子,默认为3)的值,从阈值/codeFactor,经过预热时长,才打到设置的QPS的阈值。
    • 匀速排队: 匀速排队,让请求以匀速的速度通过,阈值类型必须设置为QPS,否则无效。

Sentinel的限流

配置(以下的testA,testB都是项目cloudalibaba-sentinel-service8401的接口

1、QPS

每秒中的请求次数超过设定的阈值的时候,进行限流

2、线程数

原理: 当调用该api的线程数达到设定的阈值,进行限流
类似于在银行办业务,同一个窗口同一时间只有一个客户在办理,其他客户必须等该客户办理完之后才可以办理

如何演示:
1、设置testB的方法执行时间超过1秒,如下

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

2、设置线程数请求阈值

调用该api的方法/testB只支持一个线程,但是连续访问刷新线程数超过1个就报异常

3、关联

当关联的资源达到阈值的时候,就限流自己
eg:当与A关联的资源B达到阈值后,就限流A自己

jmeter下载地址https://archive.apache.org/dist/jmeter/source/#sig

访问:ApacheJMeter.jar测试testB接口,然后此时访问testB接口出现一下结果

4、预热

根据codeFactor(冷加载因子,默认为3)的值,从阈值/codeFactor,经过预热时长,才打到设置的QPS的阈值。
如:秒杀系统开启的瞬间,会有很多流量上来,很有可能会把系统打死,预热方式就是为了把系统保护起来, 可慢慢的吧流量放进来,慢慢的把阈值增加到设定的值

默认的codeFactor为3,即请求QPS从(threshold/3)开始,经过多少预热后才逐渐升至设定的QPS的阈值 案例:阈值10+预热时常设置5秒 系统初始化的阈值为10/3约等于3,即阈值刚开始为3,经过了5秒后阈值才慢慢升高到10


如何测试结果:
刚开始狂点testA,会发现报错Blocked by Sentinel (flow limiting),然后5秒后,阈值从3->10后,会发现狂点刷新浏览器不会出现限流

5、排队等待

让请求以均匀的请求速度通过,阈值类型必须为QPS,否则无效
设定含义/testA每秒1次请求,请超时的话需要排队等待,等待的超时时间为2000毫秒(即2秒)

浏览器一直刷新请求testB(服务被限流)

热点key限流

热点即经常访问的数据。很多时候我们希望统计某个热点数据中访问频次最高的 Top K 数据,并对其访问进行限制。

比如:
商品 ID 为参数,统计一段时间内最常购买的商品 ID 并进行限制
用户 ID 为参数,针对一段时间内频繁访问的用户 ID 进行限制
热点参数限流会统计传入参数中的热点参数,并根据配置的限流阈值与模式,对包含热点参数的资源调用进行限流。热点参数限流可以看做是一种特殊的流量控制,仅对包含热点参数的资源调用生效。

1、测试类 @SentinelResource

@GetMapping("/testHotKey")
@SentinelResource(value = "testHotKey", blockHandler = "deal_testHotKey")
public String testHotKey(@RequestParam(value = "p1", required = false) String p1,
                         @RequestParam(value = "p2", required = false) String p2) {
    return "------------------testHotKey";
}
public String deal_testHotKey(String p1, String p2, BlockException blockException) {
    //sentinel 系统默认的提示,Blocked by sentinel (flow limiting)
    return "------deal_testHotKey  ☹- _ -☹";
}

2、配置热点key接口 资源名必须和@SentinelResource的value相同

特别注意的是,如果设置了热点限流,后端的controller的方法必须有一个blockHandler方法,如果没有,则直接返回错误页面,

原理分析:网页端设置了testHotKey方法的热点限流,然后对应方法也进行了@SentinelResource注解,但是没有指定具体的blockHandler方法,所以当p1传递了参数, 并且在浏览器端的刷新次数达到了一秒钟2次的话,达到了针对testHotKey的热点限流,此时要执行该热点限流指定的blockHandler, 但是却发现没有,此时就会报错误页面的错

参数例外项

参数下标为第0个的参数(后台接收的时候知道是String,需要选择对应的数据类型),正常情况下QPS阈值为1,超过马上被限流,但是如果p1的参数值是5(p1=5)的时候,他的QPS阈值为200。
注意:

@SentinelResource处理的是Sentinel控制台配置的违规情况,有blockHandler方法配置的兜底处理。
RuntimeException int a=10/0,这个处理的是java运行时候的异常,走的是RuntimeException,所以此时@SentinelResource不管
@SentinelResource只管配置出错,运行出错走的是异常

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐