IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    Nginx limit requests module 分析

    yzprofile发表于 2012-11-16 00:00:00
    love 0

    介绍

    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



沪ICP备19023445号-2号
友情链接