在学习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的核心代码在这。//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是
\begin{equation}
x = floor(b * \frac {( 1000 / r )} {( 1000 / r – t )})
\end{equation}
虽然知道了源码但是还是没有一个非常直观的感觉,所以不如实际操作一下:
实际操作:
nginx中该模块的使用配置示例l
imit_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次,即每秒只处理一个请求,还可以有比如