在早期的计算机领域,限流技术(time limiting)被用做控制网络接口收发通讯数据的速率。 能够用来优化性能,减小延迟和提升带宽等。 如今在互联网领域,也借鉴了这个概念, 用来为服务控制请求的速率, 若是双十一的限流, 12306的抢票等。 即便在细粒度的软件架构中,也有相似的概念。 html
两种经常使用算法nginx
令牌桶(Token Bucket)和漏桶(leaky bucket)是 最经常使用的两种限流的算法。 git
漏桶算法github
它的主要目的是控制数据注入到网络的速率,平滑网络上的突发流量。漏桶算法提供了一种机制,经过它,突发流量能够被整形以便为网络提供一个稳定的流量。 漏桶能够看做是一个带有常量服务时间的单服务器队列,若是漏桶(包缓存)溢出,那么数据包会被丢弃。 用说人话的讲: redis
漏桶算法思路很简单,水(数据或者请求)先进入到漏桶里,漏桶以必定的速度出水,当水流入速度过大会直接溢出,能够看出漏桶算法能强行限制数据的传输速率。算法
在某些状况下,漏桶算法不可以有效地使用网络资源。由于漏桶的漏出速率是固定的参数,因此,即便网络中不存在资源冲突(没有发生拥塞),漏桶算法也不能使某一个单独的流突发到端口速率。所以,漏桶算法对于存在突发特性的流量来讲缺少效率。而令牌桶算法则可以知足这些具备突发特性的流量。一般,漏桶算法与令牌桶算法能够结合起来为网络流量提供更大的控制。 后端
令牌桶算法缓存
令牌桶算法的原理是系统会以一个恒定的速度往桶里放入令牌,而若是请求须要被处理,则须要先从桶里获取一个令牌,当桶里没有令牌可取时,则拒绝服务。 令牌桶的另一个好处是能够方便的改变速度。 一旦须要提升速率,则按需提升放入桶中的令牌的速率。 通常会定时(好比100毫秒)往桶中增长必定数量的令牌, 有些变种算法则实时的计算应该增长的令牌的数量, 好比华为的专利"采用令牌漏桶进行报文限流的方法"(CN 1536815 A),提供了一种动态计算可用令牌数的方法, 相比其它定时增长令牌的方法, 它只在收到一个报文后,计算该报文与前一报文到来的时间间隔内向令牌漏桶内注入的令牌数, 并计算判断桶内的令牌数是否知足传送该报文的要求。 安全
从最终用户访问安全的角度看,设想有人想暴力碰撞网站的用户密码;或者有人攻击某个很耗费资源的接口;或者有人想从某个接口大量抓取数据。大部分人都知道应该增长 Rate limiting,作请求频率限制。从安全角度,这个可能也是大部分能想到,但不必定去作的薄弱环节。服务器
从整个架构的稳定性角度看,通常 SOA 架构的每一个接口的有限资源的状况下,所能提供的单位时间服务能力是有限的。假如超过服务能力,通常会形成整个接口服务停顿,或者应用 Crash,或者带来连锁反应,将延迟传递给服务调用方形成整个系统的服务能力丧失。有必要在服务能力超限的状况下 Fail Fast。
另外,根据排队论,因为 API 接口服务具备延迟随着请求量提高迅速提高的特色,为了保证 SLA 的低延迟,须要控制单位时间的请求量。这也是 Little’s law 所说的。
还有,公开 API 接口服务,Rate limiting 应该是一个必备的功能,不然公开的接口不知道哪一天就会被服务调用方有意无心的打垮。
因此,提供资源可以支撑的服务,将过载请求快速抛弃对整个系统架构的稳定性很是重要。这就要求在应用层实现 Rate limiting 限制。
limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s; server { location /search/ { limit_req zone=one burst=5; }
详细参见: ngx_http_limit_req_module
详细参见: Haproxy Rate limit 模块
RateLimiters是令牌桶和漏桶在.NET 中实现。这些策略可用于速率限制请求不一样的网站中,后端或 API 调用等场景。
ASP.NET Web API rate limiter for IIS and Owin hosting
这个在 Redis 官方文档有很是详细的实现。通常适用于全部类型的应用,好比 PHP、Python 等等。Redis 的实现方式能够支持分布式服务的访问频率的集中控制。Redis 的频率限制实现方式还适用于在应用中没法状态保存状态的场景。
网上有众多关于这方面的文章,这里列出了本文参考的一些文档。