技术积淀---nginx限速

Nginx 限速使用的是漏桶算法,此算法图示如下,一个桶有一定的容量,水从桶的上方流入,如果桶中有水,水就会从下方按照一定的速率流出 。
当然如果桶的容量已满,流入的部分水就会溢出 。如果桶没有满,水流入速度大于流出速度,那么桶的容量就会上升 。
类比nginx环境,设置限速是1秒100个请求 。Nginx时间粒度是毫秒,也就是10ms允许通过1个请求 。那么可以认为桶的容量(10ms)是1 。如果10ms到达2个请求,那么1个请求可以通过,1个会被拒绝 。如果10毫秒到达1个请求,那么都可以顺利的通过 。这是非常简单的场景,实际上漏桶算法也会考虑burst突发的场景 。
漏桶算法桶的容量需要包括rate和burst部分 。rate表示流出速率,burst表示突发情况下,允许的最大队列 。
漏桶算法算法常被用作(Traffic Shaping)或速率限制(Rate Limiting) 。

技术积淀---nginx限速

文章插图
 
如何配置最基本的限速?
配置Nginx 配置限速主要需要两个指令limit_req_zone 用来配置限速,limit_req用来使用限速
技术积淀---nginx限速

文章插图
 
limit_req_zone一般被配置在http作用域,需要三个参数:
Key 用来设置一次请求的key,比如上图,设置的是用户二进制IP 。
Zone 设置一个共享的区域 。用来保存每个特定的IP状态,以及此IP访问被限速的url频次等 。Zone等号后面是共享区域的名字 。名字后面的冒号表示共享区域的大小 。1M空间可以保存16000个IP信息,本例子可以大约保存1.6W个IP信息 。
如果此空间被耗尽,nginx尝试去移除老的记录,但是如果空间仍然不够用的话,NGINX会返回503 (Service Temporarily Unavailable) 。
Rate 设置允许的最大请求速率 。再次强调Nginx时间粒度是毫秒,对于本例子也就是100毫秒,只允许通过一个请求 。
 
Nginx如何处理突发?
如果我们在100毫秒内收到两个请求呢?对于第二个请求,NGINX将状态码503返回给客户端 。这可能不是我们想要的,因为应用程序在本质上往往是突发的 。,我们更希望能缓冲多余的请求,尽可能及时处理 。NGINX可以通过limit_req指令的burst参数覆盖这种场景:
技术积淀---nginx限速

文章插图
 
burst参数设置,如果请求超过限速设置后,系统仍然可以接受多少请求,而不是直接拒绝 。如上图,桶的容量相当于21.如果100ms之内一个特定的IP地址,到来21个请求 。Nginx会立即将一个请求送到upstream处理 。剩下的20个请求就会入burst队列,此队列按照先进先出的方式消费 。紧接着100ms,nginx直接从队列的取出一个请求,进行消费 。如果请求超过了burst队列容量,请求依然会被拒绝 。
 
Nginx 处理触发 NoDelay 。
limit_req配置burst参数后,一定程度上支持突发的流量 。但是根据上面的介绍大家也看到了,其实消费速度还是100ms一个,只是先进了一个burst队列 。
另一种场景,假设被入队的20个请求,第20个被处理的时候已经是2s之后了 。而这20个请求是有关联的 。那么第20个请求返回给用户的时候,可能用户已经不在需要了 。
针对这种场景nginx提供了一个额外参数nodelay
技术积淀---nginx限速

文章插图
 
使用nodelay参数,当一个burst请求到达时,只要队列中有slot,nginx会立即转发,但是它将这个slot标记为“已占用”,直到适当的时间过去(在我们的示例中,在100毫秒之后)才释放它供另一个请求使用 。
假设队列20 slot是空的,并且有21个请求同时从给定的IP地址到达 。NGINX立即转发所有21个请求,并标记队列中的20个slot,然后每100毫秒释放一个slot 。(如果有25个请求,NGINX会立即转发其中21个,标记20个slot,拒绝剩下的4个请求) 。
现在假设新的100ms内,又有20个请求同时到达 。但是队列中只有一个slot被释放,因此NGINX转发一个请求,并拒绝其他19个请求 。
我们可以看到加了nodelay参数后,在突发的情况下QPS会短暂超过设置的rate 。但是从平均水平看,依旧是1秒10个 。
注意:对于大多数部署,nginx建议在limit_req指令中包含burst和nodelay参数 。
 
如何改变限速返回值?
默认情况下,当客户端超过其速率限制时,NGINX返回503(Service Temporarily Unavailable) 。使用limit_req_status指令设置不同的状态码(本例中为444):


推荐阅读