Nginx限速模块初探

  • 时间:
  • 浏览:1
  • 来源:决战梭哈棋牌APP下载_决战梭哈棋牌APP官网

从作用上来说,漏桶和令牌桶算法最明显的区别好多好多 算是允许突发流量(burst)的正确处理,漏桶算法并能强行限制数据的实时传输(正确处理)传输速率,对突发流量不做额外正确处理;而令牌桶算法并能在限制数据的平均传输传输速率的一齐允许三种程度的突发传输

使用limit_req_zone关键字,大伙定义了另一五个 名为mylimit大小为10MB的共享内存区域(zone),用来存放限速相关的统计信息,限速的key值为二进制的IP地址($binary_remote_addr),限速上限(rate)为2r/s;接着大伙使用limit_req关键字将上述规则作用到/search/上。burstnodelay的作用稍后解释。

Nginx限速模块分为哪些?按请求传输速率限速的burst和nodelay参数是哪些意思?漏桶算法和令牌桶算法究竟哪些不同?本文将带你一探究竟。大伙会通过许多简单的示例展示Nginx限速模块是怎么工作的,否则结合代码讲解其背后的算法和原理。

Nginx按请求传输速率限速模块使用的是漏桶算法,即并能强行保证请求的实时正确处理传输速率无需超过设置的阈值。

在探究Nginx限速模块事先 ,大伙先来看看网络传输中常用另一五个 的流量控制算法:漏桶算法令牌桶算法。这两只“桶”到底哪些异同呢?

漏桶算法(leaky bucket)算法思想如图所示:

算法思想是:

跟实验2相比,请求成功率没变化,否则总体耗时变短了。这怎么解释呢?实验2中,有另一五个 请求被放满burst队列当中,工作应用程序运行运行每隔1150ms(rate=2r/s)取另一五个 请求进行正确处理,最后另一五个 请求要排队2s才会被正确处理;实验3中,请求放满队列跟实验2是一样的,但不同的是,队列中的请求一齐具有了被正确处理的资格,好多好多 实验3中的五个请求可不可不能能说是一齐刚现在之前 刚开始被正确处理的,花费时间自然变短了。

关于按请求传输速率限速的原理讲解,可参考Rate Limiting with NGINX and NGINX Plus,关于源码更完整性的解析可参考ngx_http_limit_req_module 源码分析以及y123456yz的Nginx源码分析的git项目

实验2中大伙都看,通过设置burst参数,大伙可不可不能能允许Nginx缓存正确处理一定程度的突发,多余的请求可不可不能能先放满队列里,慢慢正确处理,这起到了平滑流量的作用。否则因为 队列设置的比较大,请求排队的时间就会比较长,用户深度1看来好多好多 RT变长了,这对用户很不友好。哪些正确处理土办法呢?nodelay参数允许请求在排队的事先 就立即被正确处理,也好多好多 说假如请求并能进入burst队列,就会立即被后台worker正确处理,请注意,这因为 burst设置了nodelay时,系统瞬间的QPS因为 会超过rate设置的阈值。nodelay参数要跟burst一齐使用才有作用。

令牌桶(token bucket)算法思想如图所示:

太难单个key相关的burst队列。里面代码中大伙都看当到达最后一条规则时,假如excess<limit->burst限速模块就会返回NGX_OK,并太难把多余请求放满队列的操作,这因为 Nginx是基于timer来管理请求的,当限速模块返回NGX_OK时,调度函数会计算另一五个 延迟正确处理的时间,一齐把你是什么请求放满到共享的timer队列中(一棵按等待图片时间从小到大排序的红黑树)。

Nginx主要有三种限速土办法:按连接数限速(ngx_http_limit_conn_module)、按请求传输速率限速(ngx_http_limit_req_module)。大伙着重讲解按请求传输速率限速。

漏桶算法的实现也比大伙想象的简单,其核心是你是什么行公式excess = lr->excess - ctx->rate * ngx_abs(ms) / 11150 + 11150,从前代码的意思是:excess表示当前key上遗留的请求数,本次遗留的请求数 = 上次遗留的请求数 - 预设传输速率 X 过去的时间 + 1。你是什么1表示当前你是什么请求,因为 Nginx实物表示将单位缩小了11150倍,好多好多 另一五个 请求要转添加11150。

都看这里你因为 会问,加入了nodelay参数事先 的限速算法,到底算是哪另一五个 “桶”,是漏桶算法还是令牌桶算法?当然还算是漏桶算法。考虑三种请况,令牌桶算法的token为耗尽有的是怎么做呢?因为 它另一五个 请求队列,好多好多 会把接下来的请求缓存下来,缓存2个受限于队列大小。但此时缓存哪些请求还有意义吗?因为 server因为 过载,缓存队列太难长,RT太难高,即使过了已经 请求被正确处理了,对用户来说也没哪些价值了。好多好多 当token过低用时,最明智的做法好多好多 直接拒绝用户的请求,这就成了漏桶算法,哈哈~

来看大伙的配置:

经过里面的示例,大伙队请求限速模块有了一定的认识,现在大伙深入剖析代码实现。按请求传输速率限流模块ngx_http_limit_req_module代码所处[src/http/modules/ngx_http_limit_req_module.c

](https://github.com/nginx/nginx/blob/master/src/http/modules/ngx_http_limit_req_module.c),900多好代码可谓短小精悍。相关代码有另一五个 核心数据型态:

大伙都看ngx_http_limit_req_handler()调用了函数ngx_http_limit_req_lookup(),并根据其返回值决定怎么操作:或是拒绝,或是交给下另一五个 handler正确处理,或是将请求放满定期器队列。当限速规则都通事先 ,该hanlder通过调用函数ngx_http_limit_req_account()得出当前请求时要的延迟时间,因为 不时要延迟,就将请求交给后续的handler进行正确处理,否则将请求放满定时器队列里。注意你是什么定时器队列是共享的,并太难为单独的key(比如,每个IP地址)设置队列。关于handler模块背景知识的介绍,可参考Tengine团队撰写的Nginx开发从入门到精通

使用上述规则,对于/search/目录的访问,单个IP的访问传输速率被限制在了2请求/秒,超过你是什么限制的访问将直接被Nginx拒绝。

该模块的核心逻辑在函数ngx_http_limit_req_lookup()中,你是什么函数主要流程是怎么呢?对于每另一五个 请求:

单个IP 10ms内并发发送6个请求,结果如下:

按连接数限速是指限制单个IP(因为 许多的key)一齐发起的连接数,超出你是什么限制后,Nginx将直接拒绝更多的连接。你是什么模块的配置比较好理解,详见ngx_http_limit_conn_module官方文档。

上述代码太难理解,但大伙还有2个什么的问题:

相比漏桶算法,令牌桶算法不同之所处于它不但有一只“桶”,还有个队列,你是什么桶是用来存放令牌的,队列才是用来存放请求的。

这另一五个 关键对象存储在ngx_http_limit_req_shctx_t中:

本文好多好多 对Nginx管中窥豹,更多关于Nginx介绍的文章,可参考Tengine团队撰写的Nginx开发从入门到精通。

上述代码受限算出当前key上遗留的请求数,因为 超过了burst,就直接拒绝;因为 Nginx允许多条限速规则一齐起作用,因为 已是最后一条规则,则允许通过,否则执行下一条规则。

大伙加入了burst=4,意思是每个key(此处是每个IP)最多允许另一五个 突发请求的到来。因为 单个IP在10ms内发送6个请求,结果会怎么呢?

否则请注意,嘴笨 设置burst和nodelay并能降低突发请求的正确处理时间,否则长期来看无需说会提高吞吐量的上限,长期吞吐量的上限是由rate决定的,因为 nodelay只能保证burst的请求被立即正确处理,但Nginx会限制队列元素释放的传输速率,就像是限制了令牌桶中令牌产生的传输速率。

其中除了rbtree和queue之外,还另一五个 叫做sentinel的变量,你是什么变量用作红黑树的NIL节点。

按请求传输速率限速是指限制单个IP(因为 许多的key)发送请求的传输速率,超出指定传输速率后,Nginx将直接拒绝更多的请求。采用leaky bucket算法实现。为深入了解你是什么模块,大伙先从实验什么的问题说起。刚现在之前 刚开始事先 大伙先简单介绍一下该模块的配置土办法,以下面的配置为例:

相比实验1成功数增加了另一五个 ,你是什么大伙设置的burst数目是一致的。具体正确处理流程是:另一五个 请求被立即正确处理,另一五个 请求被放满burst队列里,另外另一五个 请求被拒绝。通过burst参数,大伙使得Nginx限流具备了缓存正确处理突发流量的能力

另一五个 形象的解释是:

代码有三种返回值,它们的意思是:

实验1大伙都看,大伙短时间内发送了大量请求,Nginx按照毫秒级精度统计,超出限制的请求直接拒绝。这在实际场景中未免过于苛刻,真实网络环境中请求到来完整性有的是匀速的,很因为 有请求“突发”的请况,也好多好多 “一股子一股子”的。Nginx考虑到了你是什么请况,可不可不能能通过burst关键字开启对突发请求的缓存正确处理,而完整性有的是直接拒绝。

上述规则限制了每个IP访问的传输速率为2r/s,并将该规则作用于跟目录。因为 单个IP在非常短的时间内并发发送多个请求,结果会怎么呢?

你是什么算法的核心是:缓存请求、匀速正确处理、多余的请求直接丢弃。

LRU算法的实现很简单,因为 另一五个 节点被访问了,太难就把它移到队列的头部,当空间过低时要淘汰节点时,就选出队列尾部的节点淘汰掉,主要体现在如下代码中:

大伙有如下配置:

否则请注意:burst的作用是让多余的请求可不可不能能先放满队列里,慢慢正确处理。因为 不加nodelay参数,队列里的请求无需立即正确处理,好多好多 按照rate设置的传输速率,以毫秒级精确的传输速率慢慢正确处理。

流程很清晰,否则代码中牵涉到红黑树、LRU队列等高级数据型态,是完整性有的是会写得好多好多 样化?好在Nginx作者功力深厚,代码写得简洁易懂,哈哈~

延续实验2的配置,大伙加入nodelay选项:

本文主要讲解了Nginx按请求传输速率限速模块的用法和原理,其中burst和nodelay参数是容易引起误解的,嘴笨 可通过burst允许缓存正确处理突发请求,结合nodelay并能降低突发请求的正确处理时间,否则长期来看大伙无需说会提高吞吐量的上限,长期吞吐量的上限是由rate决定的。时要有点儿注意的是,burst设置了nodelay时,系统瞬间的QPS因为 会超过rate设置的阈值。

大伙使用单个IP在10ms内发并发送了6个请求,只另一五个 成功,剩下的五个都被拒绝。大伙设置的传输速率是2r/s,为哪些只另一五个 成功呢,是完整性有的是Nginx限制错了?当然完整性有的是,因为 Nginx的限流统计是基于毫秒的,大伙设置的传输速率是2r/s,转换一下好多好多 1150ms内单个IP只允许通过另一五个 请求,从1501ms刚现在之前 刚开始才允许通过第五个请求。