目录


滑动窗口是用来做什么的

可以使用滑动窗口进行速率限制。比如TCP的滑动窗口机制:http://timd.cn/tcp-window/

使用滑动窗口限速的好处是其比较平滑。


什么是滑动窗口

滑动窗口用来“框住”一段连续的元素序列。比如,一个时间序列,或一个环行缓冲区的子序列等。滑动窗口具有左右两个边缘,并且每个边缘都可以左移或右移。比如时间或环行缓冲区,可以被认为是向右无限延伸的,因此左边缘左移一般是一种不合规的行为。


如何实现滑动窗口

下面看hystrix中是如何实现的:

在hystrix中,一个滑动窗口,包含若干个桶(默认是10个),每个桶保存一定时间间隔内的统计数据(默认是1s)。下面看一个官方的例子:

hystrix-sliding-window.png

上图中,每个矩形框代表一个桶,每个桶记录着1秒内的4个指标数据:成功量、失败量、超时量、拒绝量。这10个桶合起来就是一个完整的滑动窗口。

从业务上讲,值得注意的是:桶对象有一个不可变的属性-windowStart,它表明该桶对象用来保存[windowStart, windowStart + bucketSizeInMillseconds)时间段内的统计信息。

从技术来讲,值得注意的是:因为每个桶都会被多个线程并发地更新指标数据,所以桶对象需要提供一些线程安全的数据结构和更新方法。为此,hystrix大量使用了CAS,而不是锁。

hystrix使用一个环形数组来维护这些桶,并且它的环形数组的实现类似于一个FIFO的队列。该数组实现有一个叫addLast(Bucket o)的方法,用于向环形数组的末尾追加新的桶对象,当数组中的元素个数没超过最大大小时,只是简单的维护尾指针;否则,在维护尾指针时,还要通过维护首指针,将第一个位置上元素剔除掉。可以看出,该环形数组的表现类似于FIFO队列。

更新统计数据时,都是向当前最新的bucket中更新的,因此hystrix的滑动窗口类HystrixRollingNumber中提供了getCurrentBucket()方法,获取当前最新的bucket。其执行流程如下:

hystrix-window.png

可以看出:滑动窗口每次只向前滑动一个bucket,因此非常的平滑。

如果想要了解hystrix,请自行查阅资料,参考文档中有hystrix的滑动窗口类HystrixRollingNumber的实现。


滚动窗口和滑动窗口

通俗点讲,滑动窗口是向前滑的,而滚动窗口是向前滚的。滑动窗口每次向前滑的距离可以小于窗口的长度,假设有两个相邻的时刻t1、t2,t1时刻的滑动窗口和t2时刻的滑动窗口是可以有交叉的。而滚动窗口向前滚的距离至少是窗口的长度,因此 ,两个相邻时刻的滚动窗口,不会有交叉。
相比之下,滚动窗口没有滑动窗口那么平滑,因为:滑动窗口会继承前一个窗口的部分信息,而滚动窗口不会继承前一个窗口的任何信息。下面是博主基于滚动窗口实现的熔断器


参考文档