概览 滑动窗口概念起源于网络通信,是一种流量控制机制。基于对指定窗口的指标统计,可以用于触发后续的处理措施。 例如分布式系统中,滑动窗口可以实现服务接口的限流。 本文针对滑动窗口在接口限流中的应用,分别提供了普通版(基于本地计数),分布式版(基于Redis计数)滑动窗口的实现。算法思路 接口限流一般是指一定单位时间内,对于某个接口的请求量不允许超过某个阈值,如果超出阈值,则会拒绝请求。 算法思路包括如下核心点: 时间窗口的创建(窗口大小,窗口最小划分周期定义) 当前所属时间窗口定位,完成计数,统计操作 其中窗口最小划分周期可以理解为窗口每次移动的步长,也是统计计数的基本单位,这个步长的大小决定了窗口是否能平滑移动,步长定义越小,滑动窗口移动得越平滑,最终的统计结果也越精确。 如下,定义了一个滑动窗口: 窗口大小为4s 窗口步长为1s,即一个窗口被拆分成4块 假设每个窗口内的请求阈值定义为10个,可以看到: 窗口1的请求总数量为8,没有达到阈值 窗口2的请求总数量为14,触发了阈值限制,因此其中有4个请求会被拒绝基本实现 代码实现思路如下。 定义滑动窗口属性: 滑动窗口实现: 统计当前窗口的请求数: 测试用例1: 熔断阈值设置为10,可以看到后10次请求都触发了熔断。 测试用例2: 熔断阈值设置为10,窗口大小为10s,第11次请求触发熔断,之后休眠10s,过渡到下一个新的窗口,后面9次请求正常执行。 Redis实现 基于Redis有序集合的特性,可以很简单就实现滑动窗口: 有序集合的score属性存储每个请求的时间戳 窗口数据统计请求量时,只需要把时间窗口外的元素舍弃,集合中剩余的元素数量之和便是结果 定义滑动窗口属性: 滑动窗口实现: 测试用例1: 熔断阈值设置为10,可以看到后10次请求都触发了熔断。 测试用例2: 熔断阈值设置为10,窗口大小为10s,第11次请求触发熔断,之后休眠10s,过渡到下一个新的窗口,后面9次请求正常执行。 测试用例3(将窗口大小调整为20s,代码与测试用例2保持一致): 窗口大小设置为20s,第11个请求之后即使休眠了10s,后面9个请求仍然触发熔断,因为这些请求还在同一个窗口内。