版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/hellow__world/article/details/78658041
在学习Nginx的时候遇到了这个问题,百度到了很多博客,大多都讲得不清不楚,在看到了
http://www.wangjingfeng.com/730.html
http://cjhust.blog.163.com/blog/static/17582715720111017114121678/
这两篇博客之后终于疑窦瞬开,在综合了之前看到的博客再加上测试案例之后整理成文。
引言: 漏斗算法(Leaky Bucket),该算法有两种处理方式Traffic Shaping和Traffic Policing 在桶满水之后,常见的两种处理方式为:
将水看作网络通信中数据包的抽象,则方式1起到的效果称为Traffic Shaping,方式2起到的效果称为Traffic Policing 由此可见,Traffic Shaping的核心理念是"等待",Traffic Policing的核心理念是"丢弃"。它们是两种常见的流速控制方法
源码: limit_req模块的源码在src/http/modules/ngx\_http\_limit\_req\_module.c,关于burst的核心代码在这。
虽然知道了源码但是还是没有一个非常直观的感觉,所以不如实际操作一下:
实际操作:
nginx中该模块的使用配置示例 limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s; server { location /search/ { limit_req zone=one burst=5 nodelay; }
第一段配置参数:
第二段配置参数:
这里的burst参数主要采用了令牌桶算法。令牌桶算法是网络流量整形(Traffic Shaping)和速率限制(Rate Limiting)中最常用的一种算法。典型情况下,令牌桶算法用来控制发送到网络上的数据数目,并允许突发数据的发送。 令牌桶这种控制机制基于令牌桶中是否存在令牌来指示什么时候可以发送流量。令牌桶中的每一个令牌都代表一个字节。如果令牌桶中存在令牌,则允许发送流量;如果令牌桶中不存在令牌,则不允许发送流量。因此,如果突发门限被合理地配置并且令牌桶中有足够的令牌,那么流量就可以以峰值速率发送。令牌桶算法的基本过程如下:
注意:令牌桶算法不能与另外一种常见算法“漏斗算法(Leaky Bucket)”相混淆。这两种算法的主要区别在于“漏斗算法”能够强行限制数据的传输速率,而“令牌桶算法”在能够限制数据的平均传输数据外,还允许某种程度的突发传输。在“令牌桶算法”中,只要令牌桶中存在令牌,那么就允许突发地传输数据直到达到用户配置的门限,因此它适合于具有突发特性的流量。(这部分是网上很多博客都错误的地方)
例子演示:
首先我们配置了limt_req_zone,rate=10r/m,即每六秒才处理一次请求,如下:
1.首先测试不加burst和不加nodelay的情况:
2.只加burst和不加nodelay的情况:
3.加burst和加nodelay的情况:
总结:
阅读更多
引言: 漏斗算法(Leaky Bucket),该算法有两种处理方式Traffic Shaping和Traffic Policing 在桶满水之后,常见的两种处理方式为:
- 暂时拦截住上方水的向下流动,等待桶中的一部分水漏走后,再放行上方水。
- 溢出的上方水直接抛弃。
将水看作网络通信中数据包的抽象,则方式1起到的效果称为Traffic Shaping,方式2起到的效果称为Traffic Policing 由此可见,Traffic Shaping的核心理念是"等待",Traffic Policing的核心理念是"丢弃"。它们是两种常见的流速控制方法
源码: limit_req模块的源码在src/http/modules/ngx\_http\_limit\_req\_module.c,关于burst的核心代码在这。
//src/http/modules/ngx_http_limit_req_module.c:396
ms = (ngx_msec_int_t) (now - lr->last);
excess = lr->excess - ctx->rate * ngx_abs(ms) / 1000 + 1000;
if (excess < 0) {
excess = 0;
}
*ep = excess;
if ((ngx_uint_t) excess > limit->burst) {
return NGX_BUSY;
}
if (account) {
lr->excess = excess;
lr->last = now;
return NGX_OK;
}
excess初始值是0,假设现在ctx->rate是2000(即2 request/s),这次请求距离上次请求是400ms。
那么excess = 0 – 2000 * 400 / 1000 + 1000 = 200。如果limit->burst是0,那么200 > 0,会返回NGX_BUSY即是503了。
假如burst是1,limit->burst即是1000,那么如果请求是每隔400ms来一个,共需5个才会填满limit->burst(每个请求将会增加200 excess),到第6个才会返回503。
推导出公式,假设设置频率是r request/s,每次请求距离上次请求t ms,设置burst为b,
那么返回503的临界请求个数x是
egin{equation}
x = floor(b * frac {( 1000 / r )} {( 1000 / r – t )})
end{equation}
虽然知道了源码但是还是没有一个非常直观的感觉,所以不如实际操作一下:
实际操作:
nginx中该模块的使用配置示例 limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s; server { location /search/ { limit_req zone=one burst=5 nodelay; }
第一段配置参数:
- $binary_remote_addr :表示通过remote_addr这个标识来做限制,“binary_”的目的是缩写内存占用量,是限制同一客户端ip地址
- zone=one:10m:表示生成一个大小为10M,名字为one的内存区域,用来存储访问的频次信息
- rate=1r/s:表示允许相同标识的客户端的访问频次,这里限制的是每秒1次,即每秒只处理一个请求,还可以有比如30r/m的,即限制每2秒访问一次,即每2秒才处理一个请求。
第二段配置参数:
- zone=one :设置使用哪个配置区域来做限制,与上面limit_req_zone 里的name对应
- burst=5:重点说明一下这个配置,burst爆发的意思,这个配置的意思是设置一个大小为5的缓冲区当有大量请求(爆发)过来时,超过了访问频次限制的请求可以先放到这个缓冲区内等待,但是这个等待区里的位置只有5个,超过的请求会直接报503的错误然后返回。
- nodelay:
- 如果设置,会在瞬时提供处理(burst + rate)个请求的能力,请求超过(burst + rate)的时候就会直接返回503,永远不存在请求需要等待的情况。(这里的rate的单位是:r/s)
- 如果没有设置,则所有请求会依次等待排队
这里的burst参数主要采用了令牌桶算法。令牌桶算法是网络流量整形(Traffic Shaping)和速率限制(Rate Limiting)中最常用的一种算法。典型情况下,令牌桶算法用来控制发送到网络上的数据数目,并允许突发数据的发送。 令牌桶这种控制机制基于令牌桶中是否存在令牌来指示什么时候可以发送流量。令牌桶中的每一个令牌都代表一个字节。如果令牌桶中存在令牌,则允许发送流量;如果令牌桶中不存在令牌,则不允许发送流量。因此,如果突发门限被合理地配置并且令牌桶中有足够的令牌,那么流量就可以以峰值速率发送。令牌桶算法的基本过程如下:
- 假如用户配置的平均发送速率为10r/s,则每隔0.1秒一个令牌被加入到桶中;
- 假设桶最多可以存发b个令牌。如果令牌到达时令牌桶已经满了,那么这个令牌会被丢弃;
- 当一个n个字节的数据包到达时,就从令牌桶中删除n个令牌,并且数据包被发送到网络;
- 如果令牌桶中少于n个令牌,那么不会删除令牌,并且认为这个数据包在流量限制之外;
- 算法允许最长b个字节的突发,但从长期运行结果看,数据包的速率被限制成常量r。对于在流量限制外的数据包可以以不同的方式处理:
- 它们可以被丢弃;
- 它们可以排放在队列中以便当令牌桶中累积了足够多的令牌时再传输;
- 它们可以继续发送,但需要做特殊标记,网络过载的时候将这些特殊标记的包丢弃。
注意:令牌桶算法不能与另外一种常见算法“漏斗算法(Leaky Bucket)”相混淆。这两种算法的主要区别在于“漏斗算法”能够强行限制数据的传输速率,而“令牌桶算法”在能够限制数据的平均传输数据外,还允许某种程度的突发传输。在“令牌桶算法”中,只要令牌桶中存在令牌,那么就允许突发地传输数据直到达到用户配置的门限,因此它适合于具有突发特性的流量。(这部分是网上很多博客都错误的地方)
例子演示:
首先我们配置了limt_req_zone,rate=10r/m,即每六秒才处理一次请求,如下:
1.首先测试不加burst和不加nodelay的情况:
- 查看当前的tcp连接数
- netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
- 结果如下:
-
- ab压测工具瞬间返回了结果
- 可以看到一共10个请求,9个请求都失败了。且0.09秒就完成了压测
- 接着查看当前的tcp连接数: 可以观察到此时服务端的TIME_WAIT 为10,这意味着是服务端主动要求断开了所有TCP连接
- 接着再查看 /var/log/nginx/access.log,印证了只有一个请求成功了,其它就是都直接返回了503,即服务器拒绝了请求。
2.只加burst和不加nodelay的情况:
- 查看当前的tcp连接数
- netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
- 结果如下:
- 使用ab测试工具,发起10个并发请求:
- ab -n 10 -c 10 url
- 可以看到测试经过30 s 才结束
- 压测中一共10个请求,有4个请求失败了,直接返回了503
- 查看当前的tcp连接数
- 上图是ab测试第一秒时的截图,TIME_WAIT=5 表示有服务器端主动断开了5个TCP连接,即5个请求被瞬时拒绝,同时ESTABLISHED的数量由23增加到28,即建立了5个TCP连接
- 上图是ab测试过程中的截图,TIME_WAIT=7 表示有服务器端主动断开了7个TCP连接,增加的2个TIME_WAIT是因为有2个在缓存队列的请求被处理完毕了,所以断开了连接。
- 上图是ab测试第一秒时的截图,TIME_WAIT=5 表示有服务器端主动断开了5个TCP连接,即5个请求被瞬时拒绝,同时ESTABLISHED的数量由23增加到28,即建立了5个TCP连接
- 接着查看 /var/log/nginx/access.log日志
- 可以观察到在39分35秒,即压测第1秒时,成功处理了1个请求,另外有4个请求瞬间返回了503,剩下的5个请求每隔6s处理一次。
- 这是因为设置了burst=5,在服务器接收到10个并发请求后,先处理1个请求,同时将5个请求放入burst缓冲队列中,等待处理。而超过(burst+1)数量的请求就被直接抛弃了,即直接抛弃了4个请求。
- 查看 /var/log/nginx/error.log日志
- 发现有5个delaying request,4个limiting request
3.加burst和加nodelay的情况:
- 查看当前的tcp连接数
- netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
- 结果如下:
- 使用ab测试工具,发起10个并发请求:
- ab -n 10 -c 10 url
- 可以看到压测在0.1 s 内完成了,这也是添加nodelay参数的意义
- 压测中一共10个请求,有4个请求失败了,直接返回了503
- 查看当前的tcp连接数:所有的请求都在1s内处理完成了
- 接着查看 /var/log/nginx/access.log日志
- 可以发现在1s内,服务器端处理了6个请求(峰值速度:burst+原来的处理速度)。对于剩下的4个请求,直接返回503,在下一秒如果继续向服务端发送10个请求,服务端会直接拒绝这10个请求并返回503。因为设定了没6s处理1个请求,所以直到30 s 之后,才可以再处理一个请求,即如果此时向服务端发送10个请求,会返回9个503,一个200
- 查看/var/log/nginx/error.log日志,发现有4个请求被直接拒绝了,没有延时请求。
总结:
- limit_req zone=req_zone;
- 严格依照在limti_req_zone中配置的rate来处理请求
- 超过rate处理能力范围的,直接drop
- 表现为对收到的请求无延时
- limit_req zone=req_zone burst=5;
- 依照在limti_req_zone中配置的rate来处理请求
- 同时设置了一个大小为5的缓冲队列,在缓冲队列中的请求会等待慢慢处理
- 超过了burst缓冲队列长度和rate处理能力的请求被直接丢弃
- 表现为对收到的请求有延时
- limit_req zone=req_zone burst=5 nodelay;
- 依照在limti_req_zone中配置的rate来处理请求
- 同时设置了一个大小为5的缓冲队列,当请求到来时,会爆发出一个峰值处理能力,对于峰值处理数量之外的请求,直接丢弃
- 在完成峰值请求之后,缓冲队列不能再放入请求。如果rate=10r/s,且这段时间内没有请求再到来,则每6 s 缓冲队列就能回复一个缓冲请求的能力,直到回复到能缓冲5个请求位置。
阅读更多
发表评论
添加代码片
还能输入1000个字符
- Edwin19911212: 感觉写的很好,而且有理有据(09-25 19:56#1楼)删除举报回复
- 上一页
- 1
- 下一页
Nginx使用limit_req_zone对同一IP访问进行限流
keketrtr 07-18 8004 nginx可以使用ngx_http_limit_req_module模块的limit_req_zone指令进行限流访问,防止用户恶意攻击刷爆服务器。ngx_http_limit_req_module模...nginx配置limit_req限制ip访问速率详解
tjcyjd 09-10 4668 1、漏桶原理 漏桶原理是什么呢?我们可以从字面上简单的理解,就是有一个桶,它的体积是固定的,桶底下有一个小洞会不停的漏水出去,而桶的上方有个水龙头,也不停的往桶里灌水。 假设我们这个桶的体积是1L,小...
nginx之ngx_http_limit_req
evsqiezi
07-02
849
配置
http{
limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
server {
location…
nginx限制请求数(ngx_http_limit_req_module) 实现详解
huzilinitachi
03-26
241
nginx ngx_http_limit_req_module可以实现限制请求IP单位时间内的请求次数的作用。限制请求数能一定程度上降低nginx以及nginx作为代理时对恶意的请求访问压力。同…
nginx 的限制连接模块limit_zone与limit_req_zone
scdxmoe
08-02
2285
http://storysky.blog.51cto.com/628458/642970/
nginx 上有两个限制连接的模块一个是 limit_zone 另一个是 limie_req_z…
nginx限制请求数(ngx_http_limit_reqmodule)模块
wanglei_storage
04-06
2332
上一篇文章主要写nginx限制连接数ngx_http_limit_conn_module 模块的作用及使用方法,下面来写ngx_http_limit_req_module模块的作用及使用。通过ngx…
十六.更强大的防攻击(访问速度限制)模块,对Nginx的limit_req增强
u010889990
12-09
1418
1.白名单支持
Syntax: limit_req_whitelist geo_var_name=var_name geo_var_value=var_value
Default: -
…
Nginx PHP 使用 limit_req,limit_conn 限制并发,外加白名单
abc86319253
03-18
1540
出处: http://blog.segmentfault.com/qianfeng/1190000000420242
下面方法可以防止黑客知道你的源服务器真实IP进行并发攻击,通常只需要…
相关热词
nginx
nginx和
nginx之
nginx打开
nginx模式
没有更多推荐了,返回首页