前言:大家好,我是小威,24届毕业生,在一家满意的公司实习。本篇文章将详细介绍如何Sentinel如何使用滑动窗口进行限流和降级,后续文章将详细介绍其他知识。
如果文章有什么需要改进的地方还请大佬不吝赐教👏👏。
小威在此先感谢各位大佬啦~~🤞🤞
🏠个人主页:小威要向诸佬学习呀
🧑个人简介:大家好,我是小威,一个想要与大家共同进步的男人😉😉
目前状况🎉:24届毕业生,在一家满意的公司实习👏👏💕欢迎大家:这里是CSDN,我总结知识的地方,欢迎来到我的博客,我亲爱的大佬😘
以下正文开始
文章目录
- Sentinel滑动窗口前言
- Sentinel滑动窗口原理
- 如何在项目中使用滑动窗口
Sentinel滑动窗口前言
Sentinel 是一个开源的高可用性、高扩展性的实时流量控制框架,它可以用于保护服务稳定性,防止系统因为流量过大而崩溃。今天我们所介绍的,是滑动窗口,它是 Sentinel 实现限流和降级的重要组件之一。
Sentinel滑动窗口原理
滑动窗口通常由一个固定大小的时间窗口和一个可滑动的数据结构组成,例如队列或滑动块。在 Sentinel 中,滑动窗口被分为计数器类型和预算类型:
计数器滑动窗口:计数器滑动窗口维护一个周期内请求的总数,当周期结束后,滑动窗口会被清空,开始下一个周期的计数。在 Sentinel 中,计数器滑动窗口通过 AtomicLong 数组实现,数组的长度代表时间窗口的大小,每个元素代表该时间片保存的请求次数。
预算滑动窗口:预算滑动窗口维护周期内预算资源的使用情况,以便根据实际资源需要进行限流或降级。预算类型的滑动窗口可以设置阈值,并支持动态调整。在 Sentinel 中,预算滑动窗口通常用于 CPU 使用率、线程池等容量资源的控制。
除此之外,Sentinel 还提供了基于单机、集群和分布式三种模式的滑动窗口实现。其中,单机模式下将使用本地内存来维护滑动窗口数据结构;集群模式下,各节点会通过多播或 Redis 等方式共享相同的计数器数据;分布式模式下,则允许多个服务节点公用同一组滑动窗口数据。
在使用 Sentinel 进行限流和降级时,用户可以通过配置规则来指定需要监控的目标资源,并设置相应的阈值和处理策略。例如,在限流场景下,用户可以设置最大 QPS,并指定超过该阈值的请求将会被丢弃或返回特定的错误码。在降级场景下,用户可以设置响应时间、异常比例等阈值,并指定相应的降级策略,例如返回默认值或者直接抛出异常。
如何在项目中使用滑动窗口
以实际的项目为例子,我们有一个服务用于提供用户信息查询接口,每秒钟最多只能处理 10 次查询请求,并且如果连续 5 秒内的请求次数超过 50 次,则触发限流或降级操作。
在 Sentinel 中,我们首先需要定义一个 FlowRule 数组用于配置针对该服务的限流规则,在这块项目例子中,它们是每秒钟限流到 10 个请求和 5 秒内超过 50 次请求两种限制:
FlowRule rule1 = new FlowRule();
rule1.setResource("queryUser");
rule1.setCount(10);
rule1.setGrade(RuleConstant.FLOW_GRADE_QPS);
FlowRule rule2 = new FlowRule();
rule2.setResource("queryUser");
rule2.setCount(50);
rule2.setGrade(RuleConstant.FLOW_GRADE_QPS);
rule2.setStrategy(RuleConstant.STRATEGY_CHAIN);
rule2.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_WARM_UP);
我们先对以上代码进行解释,“queryUser” 代表资源名称,这个可以自己定义,然后设置了resource、count、grade以及对于第二个规则还增加了三个属性stratety, controlBehavior和controlBehavior。其中 count 表示限流阈值,即每秒钟最多可以处理多少个请求;grade 表示限流模式,QPS(每秒钟最多允许通过的请求数量);strategy 表示限流策略;controlBehavior 表示流量控制的行为。
接下来,我们需要通过执行如下代码初始化 Sentinel:
List<FlowRule> rules = new ArrayList<>();
rules.add(rule1);
rules.add(rule2);
FlowRuleManager.loadRules(rules);
我们这里定义了一个 FlowRule 数组,将前面定义好的两个规则加入到列表中,然后通过 FlowRuleManager.loadRules() 方法加载这些规则。
现在,我们可以在查询用户信息的方法上增加 @SentinelResource 注解,并在该注解中设置 blockHandler 和 fallback 属性来处理限流和降级异常:
@SentinelResource(value = "queryUser", blockHandler = "queryUserBlockHandler",
fallback = "queryUserFallback")
public UserInfo queryUser(String userId) {
// 查找用户信息的实现
}
// 限流/降级处理函数
public UserInfo queryUserBlockHandler(String userId, BlockException ex) {
// 返回具体的错误信息
}
// 降级处理
public UserInfo queryUserFallback(String userId, Throwable ex) {
// 返回降级后的响应
}
以上代码中我们定义了一个名为“queryUser”的资源,它被 @SentinelResource 注解所修饰,blockHandler 属性表示当该服务触发限流或降级时调用的函数,fallback 属性表示服务出现异常时的回退函数。
最后,我们可以通过对定时任务进行调度,模拟10秒内对同一个 API 请求用户数据的场景,例如代码如下:
public class QueryUserTask implements Runnable {
private static final Random random = new Random();
@Override
public void run() {
// 模拟 10 秒内对同一个 API 请求用户数据
for (int i = 0; i < 20; i++) {
String userId = "user-" + (i % 5);
queryUser(userId);
try {
Thread.sleep(random.nextInt(500));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
我们可以在 QueryUserTask 内部实现每隔一秒获取一次用户信息,检测系统是否触发限流或降级保护。如果触发了规则中配置的限流规则,那么 Sentinel 将执行相应的措施进行处理。
好了,本篇文章就先分享到这里了,后续将会继续介绍sentinel详细的其他方面的知识,感谢大佬认真读完支持咯~
文章到这里就结束了,如果有什么疑问的地方请指出,诸佬们一起讨论😁
希望能和诸佬们一起努力,今后我们顶峰相见🍻
再次感谢各位小伙伴儿们的支持🤞