Nginx Limit requests module: http://wiki.nginx.org/HttpLimitReqModule
This module allows you to limit the number of requests for a given session, or as a special case, with one address.
Restriction done using leaky bucket.
Limit requests使用的是漏桶算法.http://en.wikipedia.org/wiki/Leaky_bucket
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;
}
lr->count++;
ctx->node = lr;
return NGX_AGAIN;
ctx->rate在配置解析时转换为QPS,并放大了1000倍以增加计算精度。
excess = lr->excess - ctx->rate * ngx_abs(ms) / 1000 + 1000
,这个是将整个式子 * 1000来增大计算精度的,还原之后是:
excess = lr->excess - qps / 1000 * ngx_abs(ms) + 1
, 当前时刻还能允许进入请求的余量。
burst的值也就是类似一个水桶,当excess余量大于burst上限时请求溢出直接就被拒绝了,当其大于0还没超出水桶上限时limit request模块会给请求加上定时器,延后处理,控制流速(这是在delay模式下)。
r->read_event_handler = ngx_http_test_reading;
r->write_event_handler = ngx_http_limit_req_delay;
ngx_add_timer(r->connection->write, delay);
延后时间为 delay = excess.其可将请求拉成匀速流向后端。当burst值(水桶)越大,hold住的请求也就越多,在有流量突发的时候也能以限定的速度去处理,减少后端压力。但是会导致RT普遍偏高。
在nodelay的模式下时,实际上应该被称作token bucket算法。即没有超过水桶上限的流量都会被立即处理,超出的被拒绝。nodelay是允许突发值的,这样也就给后端在请求突增的时候带来了不确定的压力。正常情况下用户体验要比delay好,它会及时响应用户的请求而不控制流速。不会像delay状态下增加用户rt时间。
hava fun :)
EOF