《SpringCloud Alibaba 微服务架构》专题(十四)-Spring Cloud AlibabaSentinel之热点参数限流

1.引言

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

  • 商品ID为参数,统计一段时间内最常购买的商品ID并进行限制
  • 用户ID为参数,针对一段时间内频繁访问的用户ID进行限制

热点参数限流会统计传入参数中的热点参数,并根据配置的限流阈值与模式,对包含热点参数的资源调用进行限流。热点参数限流可以看做是一种特殊的流量控制,仅对包含热点参数的资源调用生效。
在这里插入图片描述
Sentinel 利用LRU策略统计最近最常访问的热点参数,结合令牌桶算法来进行参数级别的流控。热点参数限流支持集群模式。

2.热点参数规则

热点参数规则(ParamFlowRule)类似于流量控制规则(FlowRule

属性说明默认值
resource资源名,必填
count限流阈值,必填
grade限流模式QPS 模式
durationInSec统计窗口时间长度(单位为秒),1.6.0 版本开始支持 模式1s
controlBehavior流控效果(支持快速失败和匀速排队模式),1.6.0 版本开始支持快速失败
maxQueueingTimeMs最大排队等待时长(仅在匀速排队模式生效),1.6.0 版本开始支持0ms
paramIdx热点参数的索引,必填,对应 SphU.entry(xxx, args) 中的参数索引位置
paramFlowItemList参数例外项,可以针对指定的参数值单独设置限流阈值,不受前面 count 阈值的限制。仅支持基本类型和字符串类型
clusterMode是否是集群参数流控规则false
clusterConfig集群流控相关配置

3.热点参数限流案例

前面我们已经了解了什么是热点参数限流,下面通过案例说明如何配置以及Sentinel是如何限流的。

【a】控制层添加如下方法

package com.bruce.controller;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

/**
 * @BelongsProject: springcloud-alibaba-nacos
 * @BelongsPackage: com.bruce.controller
 * @CreateTime: 2021-02-20 17:19
 * @Description: TODO
 */
@RestController
@Slf4j
public class HotKeyRuleController {

    /**
     * @SentinelResource: 指定资源名称,作用与HystrixCommand大体一致
     * blockHandler: 指定降级处理方法,类似于Hystrix的fallbackMethod兜底方法
     */
    @GetMapping("/testHotKeyRule")
    @SentinelResource(value = "testHotKeyRule", blockHandler = "testHotKeyRule_blockHandler")
    public String testHotKeyRule(@RequestParam(value = "username", required = false) String username,
                                 @RequestParam(value = "password", required = false) String password) {
        return "[热点限流规则]testHotKeyRule..";
    }

    public String testHotKeyRule_blockHandler(@RequestParam(value = "username", required = false) String username,
                                              @RequestParam(value = "password", required = false) String password,
                                              BlockException exception) {
        return "[热点限流规则-兜底方法]testHotKeyRule_blockHandler..";
    }

}

重启项目,浏览器访问: http://localhost:8401/testHotKeyRule
在这里插入图片描述
说明我们接口是通的,下面我们看看如何配置。

【b】Sentinel热点限流配置,具体配置如下图
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
上面的配置表示:当访问testHotKeyRule资源的时候,针对方法testHotKeyRule的第一个参数【这里对应我们controller中的username参数】的请求,如果一秒内的请求阈值QPS超过1次,那么将会触发兜底方法。

浏览器访问: http://127.0.0.1:8401/testHotKeyRule?username=bruce
在这里插入图片描述
注意,这时候我们是一秒内访问一次,可以看到,接口正常返回数据。
突然,我们增加请求接口的频率,手动触发一秒内请求次数大于1次:
在这里插入图片描述
可见,当违反上面的配置请求规则时,马上降级处理,成功执行我们指定的blockHandler兜底方法。

下面我们访问:http://localhost:8401/testHotKeyRule?password=123456,注意这个请求并没有包含我们Sentinel配置的参数索引为0的参数【username】,不管我们一秒一次请求还是一秒内疯狂请求资源:
在这里插入图片描述
可以看到,当请求接口未包含指定的限流Key时,是不会触发blockHandler兜底方法的。

4.热点限流-参数例外项

前面我们介绍了普通版的热点参数限流,当第一个参数访问次数超过一秒钟一次后,达到阈值1后马上被限流,但我们有时候期望我们的限流参数Key当它是某个特殊值时,它的限流值和平时不一样。所以Sentinel提供了参数例外项的配置以满足这种特殊需求。

例如:假如前面我们的第一个参数username=bruce的时候,它的阈值可以达到500。
在这里插入图片描述
【a】Sentinel参数例外项配置
在这里插入图片描述
【b】测试

浏览器疯狂访问:http://localhost:8401/testHotKeyRule?username=bruce123
在这里插入图片描述

可以看到,当参数的值不满足例外项配置的值时,默认还是走普通的限流【一秒超过一次就直接降级】。

下面我们测试参数例外项: http://localhost:8401/testHotKeyRule?username=bruce

因为我们前面配置当参数的值等于"bruce"的时候,QPS阈值时500,所以当我们在浏览器一直刷新的时候,一秒钟内基本上不可能超过访问阈值500,所以也就不会触发降级方法。如下图所示:
在这里插入图片描述
下面我们说一个需要特别注意的地方,我们在业务方法里面模拟发生异常:

@GetMapping("/testHotKeyRule")
@SentinelResource(value = "testHotKeyRule", blockHandler = "testHotKeyRule_blockHandler")
 public String testHotKeyRule(@RequestParam(value = "username", required = false) String username,
                              @RequestParam(value = "password", required = false) String password) {
     int i = 10 / 0;
     return "[热点限流规则]testHotKeyRule..";
 }

重启项目,浏览器访问:http://localhost:8401/testHotKeyRule?username=bruce,
在这里插入图片描述
可以看到,直接将除数为0的报错展示出来了,并不会降级处理, 这里小伙伴们千万别搞错了, blockHandler兜底方法只针对你在Sentinel中配置的限流规则,当你违反了之后才会走兜底降级方法;如果是业务抛出的异常,Sentinel并不会降级处理。

小总结:

@SentinelResource:处理的是Sentinel控制台配置的违规情况,有blockHandler方法配置的兜底处理;

RuntimeException:java运行时抛出的运行时异常,@SentinelResource不管,@SentinelResource主管配置出错,运行该走异常还是走异常。

5.总结

热点参数限流规则主要是针对请求参数来统计,并实现限流的。首先热点参数是基于QPS统计,如果参数索引设置为0,则以第一个参数统计为准,阈值也是按照基本参数中的阈值来控制的,但是指定的是额外的参数列表的下标,则需要提供指定的热点参数的值,如果当前访问的参数与预设定的参数不一致,依旧与第一个参数的阈值为准。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

熊猫-IT

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值