Nginx如何限流

这篇文章主要介绍了Nginx如何限流,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。

创新互联公司10多年企业网站建设服务;为您提供网站建设,网站制作,网页设计及高端网站定制服务,企业网站建设及推广,对成都资质代办等多个方面拥有多年建站经验的网站建设公司。

1   漏桶和令牌桶算法的概念

漏桶算法(Leaky Bucket):主要目的是控制数据注入到网络的速率,平滑网络上的突发流量。漏桶算法提供了一种机制,通过它,突发流量可以被整形以便为网络提供一个稳定的流量。漏桶算法的示意图如下图所示,请求先进入到漏桶里,漏桶以一定的速度出水,当水请求过大会直接溢出,可以看出漏桶算法能强行限制数据的传输速率。

Nginx如何限流

令牌桶算法(Token Bucket):是网络流量整形(Traffic Shaping)和速率限制(Rate Limiting)中最常使用的一种算法。典型情况下,令牌桶算法用来控制发送到网络上的数据的数目,并允许突发数据的发送。令牌桶算法示意图如下图所示,大小固定的令牌桶可自行以恒定的速率源源不断地产生令牌。如果令牌不被消耗,或者被消耗的速度小于产生的速度,令牌就会不断地增多,直到把桶填满。后面再产生的令牌就会从桶中溢出。最后桶中可以保存的最大令牌数永远不会超过桶的大小。

Nginx如何限流

2   两种算法的区别

两者主要区别在于“漏桶算法”能够强行限制数据的传输速率,而“令牌桶算法”在能够限制数据的平均传输速率外,还允许某种程度的突发传输。在“令牌桶算法”中,只要令牌桶中存在令牌,那么就允许突发地传输数据直到达到用户配置的门限,所以它适合于具有突发特性的流量。

3  按请求速率限速

按请求速率限速是指限制IP发送请求的速率,超出指定速率后,Nginx将直接拒绝更多的请求。采用漏桶算法实现。下面从一些实验数据上来深入的了解这个模块,先简单介绍一下该模块的配置方式,如下图所示(配置需要在Nginx配置和域名配置里面同时修改),使用limit_req_zone关键字,定义一个名为tip大小为10MB的共享内存区域(zone),用来存放限速相关的统计信息,限速的key值为二进制的IP地址($binary_remote_addr),限速上限(rate)为2r/s。

将上述规则应用到/search目录(单个IP的访问速度被限制在了2请求/秒,超过这个限制的访问将直接被Nginx拒绝)。burst和nodelay的作用稍后解释。(zone=tip:10m表示会话空间的存储大小为10m)。

Nginx如何限流

4   3个实验案例

实验1、讨论2个请求在1s内的执行过程

修改配置下图所示:

Nginx如何限流

我们使用ab工具模拟1s发送2个请求。

Nginx如何限流

只有一个请求成功了,查看了一下执行时间:

Nginx如何限流

1ms内完成了所有请求,考虑到每秒两个请求可能是分时间段来来完成的,二分法做了大量延迟处理的尝试,当两个请求之间的时延大于0.5s时第二个请求才会成功。

Nginx如何限流

结论:Nginx的限流统计是基于毫秒的,我们设置的速度是2r/s,转换一下就是500ms内单个IP只允许通过1个请求,从501ms开始才允许通过第二个请求。

Nginx如何限流

实验2、burst允许缓存处理突发请求

如果短时间内发送了大量请求,Nginx按照毫秒级精度统计,超出限制的请求直接拒绝。这在实际场景中未免过于苛刻,真实网络环境中请求到来不是匀速的,很可能有请求“突发”的情况。Nginx考虑到了这种情况,可以通过burst关键字开启对突发请求的缓存处理,而不是直接拒绝。(类似令牌桶算法)

修改Nginx配置如下:

Nginx如何限流

我们加入了burst=4,意思是每个key(此处是每个IP)最多允许4个突发请求的到来。使用ab工具发送6个请求,结果会怎样呢?

Nginx如何限流

发送时间:

Nginx如何限流

执行结果是请求全部被处理,加入缓冲队列后,按照之前时间轴的规则 ,在0.001s、0.501s、1.001s、1.501s、2.001s、2.501s分别发送一个请求,与之前的有些偏差,理论上数据应该是同时发送到ngnix,我们做了抓包统进行验证,可以观察到6个请求分别开辟了6个端口进行发送,只有当第一个包三次握手完成,第二个包才开始发送,时间间隔500ms,这就验证了ab工具确实是单个发送的。

Nginx如何限流

另外,理论上缓冲区之外的2个请求应该只有一个是200,另外一个是503,缓冲区的4个请求是按照2r/s的速度依次处理,这里是由于ab工具本身的问题,在加入缓冲队列后,发送时间由之前的1ms内完成变成了2501ms完成,所以导致了请求都被处理掉,若是使用其他工具短时间内发送6个请求,则只能成功5个。

Nginx如何限流

发送耗时2ms,完成处理时间2437ms,每个请求的处理时间。

Nginx如何限流

由于ngnix 500ms处理完第一个请求后,501ms才会处理第二个请求,所以5个请求(去掉503那个)耗时500ms*4+416ms=2416ms(本地实测,不同Nginx性能有所差异),或者使用ab工具并发来处理这些请求,也会有同样的效果。

Nginx如何限流

我们再来观察一下发送时间,所有的请求基本在10ms内发起,这样便导致了6个请求中,去掉第一个和缓冲区的4个,第二个被拒绝掉。

Nginx如何限流

实验3、nodelay降低排队时间

通过设置burst参数,我们可以允许Nginx缓存处理一定程度的突发,多余的请求可以先放到队列里,慢慢处理,这起到了平滑流量的作用。但是如果队列设置的比较大,请求排队的时间就会比较长,这对用户很不友好。nodelay参数允许请求在排队的时候就立即被处理,也就是说只要请求能够进入burst队列,就会立即被后台worker处理。

延续实验2的配置,我们加入nodelay选项:

Nginx如何限流

同样发送6个请求发送时间:

Nginx如何限流

实验结果如下图所示:

Nginx如何限流

处理时间:

Nginx如何限流

与实验2相比直观上的效果就是Nginx同时出现6条日志,即6个请求是同时被处理的,而实验2日志是逐条生成的,间隔0.5s,视觉上有卡顿。

虽然设置burst和nodelay能够降低突发请求的处理时间,但是长期来看并不会提高吞吐量的上限,长期吞吐量的上限是由rate决定的,因为nodelay只能保证burst的请求被立即处理,加入了nodelay参数之后的限速算法还算是漏桶算法,当令牌桶算法的token为耗尽时,由于它有一个请求队列,所以会把接下来的请求缓存下来,缓存多少受限于队列大小。假如server已经过载,缓存队列越来越长,即使过了很久请求被处理了,对用户来说也没什么价值了。所以当token不够用时,最明智的做法就是直接拒绝用户的请求,即漏桶算法。

感谢你能够认真阅读完这篇文章,希望小编分享的“Nginx如何限流”这篇文章对大家有帮助,同时也希望大家多多支持创新互联,关注创新互联行业资讯频道,更多相关知识等着你来学习!


文章标题:Nginx如何限流
网页链接:http://scyanting.com/article/gjshog.html