滑动窗口计算器如何对多个接口限流_浅谈sentinel限流

1.常见限流算法
计数器算法

在指定周期内累加访问次数,当访问次数达到阈值时触发限流,当进入下一个时间周期时进行访问次数的清零。
问题:临界问题,相邻两个周期时间段内访问次数可能超出限制,但并未限流。

滑动窗口算法

在固定窗口中分割出多个小时间窗口,然后根据时间将窗口向前滑动并删除过期的小时间窗口,最终只统计滑动窗口范围内的所有小时间窗口总的计数。

令牌桶限流算法
  • 固定大小的令牌桶(即限制最大请求量)

  • 系统以恒定速度(r token/sec)往令牌桶中放入令牌

  • 客户端请求执行前需要先获取并消耗令牌桶中的令牌

  • 当请求速度大于令牌生成速度,令牌会被很快消耗,从而达到限流效果

问题:短时间内的突发流量无法处理

漏桶限流算法
  • 内部维护一个容器

  • 容器以恒定速度流出流量

  • 当请求速度大于容器流出速度,则会触发限流

2.服务熔断

当服务无法提供正常服务时,为了防止雪崩效应,暂时将出现故障的接口隔离开来,后续一段时间调用的请求直接失败,直到目标服务恢复正常。
判断指标:平均响应时长,异常比例,异常数量

3.服务降级

将一些不重要的业务或接口的功能降低,可以只提供部分功能,也可以完全停掉所有不重要的功能。

4.Sentinel dashboard安装

启动命令

java -jar sentinel-dashboard.jar

-Dserver.port=8080 用于指定 Sentinel 控制台端口为 8080

-Dcsp.sentinel.dashboard.server=localhost:8080 用于控制台对外暴露的服务地址

-Dproject.name=sentinel-dashboard 项目名称

-Dsentinel.dashboard.auth.username=sentinel 用于指定控制台的登录用户名为 sentinel;

-Dsentinel.dashboard.auth.password=123456 用于指定控制台的登录密码为 123456;如果省略这两个参数,默认用户和密码均为 sentinel;

-Dserver.servlet.session.timeout=7200 用于指定 Spring Boot 服务端 session 的过期时间,如 7200 表示 7200 秒;60m 表示 60 分钟,默认为 30 分钟;

5.Sentinel实现流量限制
定义规则

List<FlowRule> rules = new ArrayList()<>;

FlowRule rule = new FlowRule();

// 资源名

rule.setResource(“resource1”);

// 限流阈值类型,QPS模式1,并发线程模式2

rule.setGrade(RuleConstant.FLOW_GRADE_QPS);

// 是否根据来源进行限流,默认未default,即不区分

rule.setLimitApp(“default”);

// 调用关系限流策略,直接,链路,关联

rule.setStrategy(RuleConstant.STRATEGY_CHAIN);

// 流控行为,直接拒绝,排队等待,慢启动模式,默认直接拒绝

rule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_DEFAULT);

// 是否为集群限流

rule.setClusterMode(false);

// 限流阈值

rule.setCount(20);

rules.add(rule);

FlowRuleManager.loadRules(rules);

限流

try (Entry entry = SphU.entry(“resource1”)) {

// 业务逻辑

} catch (BlockException e) {

// 限流会抛出BlockException

}

注解形式

@SentinelResource(value = “resourceName”, blockHandler = “blockHandlerForResource1”)

Grade属性

FLOW_GRADE_THREAD(统计当前请求的上下文线程数量)
FLOW_GRADE_QPS(统计每秒查询数)

QPS流量控制行为

直接拒绝
Warm Up(冷启动(预热)):系统并不是直接将QPS限制拉到最大,而是逐步增加阈值
匀速排队:严格控制请求通过的间隔时间,也就是让请求以匀速的速度通过,类似于漏桶限流算法

调用关系流量策略
  • 调用方限流:
    根据请求来源进行流量控制,需要设置limitApp属性来设置来源信息
    default:表示不区分调用者,也就是任何访问调用者的请求都会进行限流统计
    {some_origin_name}:设置特定的调用者,只有来自这个调用者的请求才会进行流量统计和控制
    other:表示针对除{some_origin_name}外的其他调用者进行流量控制

  • 根据调用链路入口限流:

  • 关联流量控制:两个资源之间存在关联时,只限制其中一个资源

6.Sentinel实现服务熔断

List<DegradeRule> rules = new ArrayList()<>;

DegradeRule rule = new DegradeRule();

// 资源名

rule.setResource(“resource1”);

// 熔断策略

rule.setGrade(RuleConstant.DEGRADE_GRADE_RT);

// 限流阈值

rule.setCount(10);

// 触发熔断降级后多长时间内自动熔断,单位s

rule.setTimeWindow(10);

// 触发熔断的最小请求数,请求数小于该值时即使异常比例超过阈值也不会触发熔断,默认5

rule.setMinRequestAmount(5);

// Grade为RT时,1s内持续多少个请求平均RT超出阈值触发熔断,默认5

rule.setRtSlowRequestAmount(5);

rules.add(rule);

三种熔断策略:
  • 平均响应时间(RuleConstant.DEGRADE_GRADE_RT)
    如果1s内持续进入5个请求,对应的平均响应时间都超过了阈值(count,单位ms)那么接下来的时间窗口(timeWindow,单位s)内,进行自动熔断,抛出DegradeException

  • 异常比例(RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO)
    如果每秒资源数 >= minRequestAmount(默认5),并且每秒异常占比超过阈值count(count的取值范围[0.0,1.0],代表0%到100%),则进行熔断…

  • 异常数(RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT)
    当资源最近一分钟的异常数目超过阈值后,触发熔断

7.热点数据限流

List<ParamFlowRule> rules = new ArrayList()<>;

ParamFlowRule rule = new ParamFlowRule(“resource1”);

// 热点参数的索引

rule.setParamIdx(0);

// 限流阈值类型,QPS模式1,并发线程模式2

rule.setGrade(RuleConstant.FLOW_GRADE_QPS);

// 限流阈值

rule.setCount(20);

rules.add(rule);

ParamRuleManager.loadRules(rules);

8.使用
客户端引入依赖

com.alibaba.cloud

spring-cloud-starter-alibaba-sentinel

2.1.1.RELEASE

yml配置:

spring:

cloud:

sentinel:

transport:

dashboard: localhost:9100

配置规则

10e88834a04a9ac1bf0def908f1046b2.png

阈值类型/单机阈值:

  • QPS:每秒的请求量达到阈值,进行限流

  • 线程数:当调用该api的线程数达到阈值时进行限流

流控模式:

  • 直接:api达到限流条件时,直接限流

  • 关联:当关联的资源达到阈值时,就限流自己

  • 链路:只记录指定链路上的流量(指定资源从入口资源进来的流量,如果达到阈值,就进行限流,但其它入口进来的不会限流)

5aac5a0df3e83c2e7a2d61378432534e.png

e5ad52f150e43981af2651a2e26daa3b.png

熔断策略:

  • RT:平均响应时间(秒级统计)超出阈值 且 在时间窗口内的请求 >= 5时,触发降级(断路器打开);时间窗口结束后,关闭降级【Sentinel默认最大的RT为4900ms,可以通过-Dcsp.sentinel.statistic.max.rt=xxx修改】

  • 异常比例:QPS >= 5 且异常比例(秒级统计)超过阈值时,触发降级;时间窗口结束后,关闭降级

  • 异常数:异常数(分钟统计)超过阈值时,触发降级;时间窗口结束后,关闭降级【时间窗口 < 60秒可能会出现问题】
    关于异常数这种降级策略需要注意的点:
    若将时间窗口的值设置小于60秒则可能会出问题,因为异常数的统计是分钟级别的,时间窗口小于60秒就有可能不断进入降级状态.
    spring cloud sentinel 处理的场景是 feign 远程调用的降级异常 tracer 记录了。
    普通异常需要手动加Tracer.trace(e);

53d3ec43cbe04a8fd7b681e218df7751.png

需要自己添加资源@SentinelResource(value = “resourceName”)

参数例外项:指定参数值进行额外限流

4f4916268de2c62e29d7b5c4a3dba773.png

  • LOAD:(仅对 Linux/Unix-like 机器生效):当系统 load1 超过阈值,且系统当前的并发线程数超过系统容量时才会触发系统保护。系统容量由系统的 maxQps minRt 计算得出。设定参考值一般是 CPU cores 2.5

  • RT:当单台机器上所有入口流量的平均 RT(响应时间) 达到阈值即触发系统保护,单位是毫秒

1796462796f4e5d4cdf03c6c36a56652.png

流控应用(limitApp)指的时调用方的服务名

自定义限流异常

@Component

@Slf4j

public class MyBlockHandler implements BlockExceptionHandler {

@Override

public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, BlockException e) throws Exception {

if (e instanceof FlowException) {

log.error("限流异常");

} else if (e instanceof DegradeException) {

log.error("降级异常");

} else if (e instanceof ParamFlowException) {

log.error("热点参数异常");

} else if (e instanceof SystemBlockException) {

log.error("系统异常");

} else if (e instanceof AuthorityException) {

log.error("授权异常");

}

httpServletResponse.setStatus(HttpStatus.OK.value());

R r = R.fail(ErrorCode.SENTINEL.getCode(), e.getMessage());

httpServletResponse.setHeader("Content-Type", "application/json;charset=utf-8");

httpServletResponse.getWriter().print(JSON.toJSONString(r));

httpServletResponse.getWriter().flush();

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值