# HG changeset patch # User Maxim Dounin # Date 1542815810 -10800 # Node ID d6ca744c727eec67773eaf14b13a7fa80de41d55 # Parent bca4dad0d3cb459173b6ee573c53e9d99f4df5d4 Limit req: "delay=" parameter. This parameter specifies an additional "soft" burst limit at which requests become delayed (but not yet rejected as it happens if "burst=" limit is exceeded). Defaults to 0, i.e., all excess requests are delayed. Originally inspired by Vladislav Shabanov (http://mailman.nginx.org/pipermail/nginx-devel/2016-April/008126.html). Further improved based on a patch by Peter Shchuchkin (http://mailman.nginx.org/pipermail/nginx-devel/2018-October/011522.html). diff --git a/src/http/modules/ngx_http_limit_req_module.c b/src/http/modules/ngx_http_limit_req_module.c --- a/src/http/modules/ngx_http_limit_req_module.c +++ b/src/http/modules/ngx_http_limit_req_module.c @@ -44,7 +44,7 @@ typedef struct { ngx_shm_zone_t *shm_zone; /* integer value, 1 corresponds to 0.001 r/s */ ngx_uint_t burst; - ngx_uint_t nodelay; /* unsigned nodelay:1 */ + ngx_uint_t delay; } ngx_http_limit_req_limit_t; @@ -499,12 +499,12 @@ ngx_http_limit_req_account(ngx_http_limi excess = *ep; - if (excess == 0 || (*limit)->nodelay) { + if ((ngx_uint_t) excess <= (*limit)->delay) { max_delay = 0; } else { ctx = (*limit)->shm_zone->data; - max_delay = excess * 1000 / ctx->rate; + max_delay = (excess - (*limit)->delay) * 1000 / ctx->rate; } while (n--) { @@ -544,11 +544,11 @@ ngx_http_limit_req_account(ngx_http_limi ctx->node = NULL; - if (limits[n].nodelay) { + if ((ngx_uint_t) excess <= limits[n].delay) { continue; } - delay = excess * 1000 / ctx->rate; + delay = (excess - limits[n].delay) * 1000 / ctx->rate; if (delay > max_delay) { max_delay = delay; @@ -875,9 +875,9 @@ ngx_http_limit_req(ngx_conf_t *cf, ngx_c { ngx_http_limit_req_conf_t *lrcf = conf; - ngx_int_t burst; + ngx_int_t burst, delay; ngx_str_t *value, s; - ngx_uint_t i, nodelay; + ngx_uint_t i; ngx_shm_zone_t *shm_zone; ngx_http_limit_req_limit_t *limit, *limits; @@ -885,7 +885,7 @@ ngx_http_limit_req(ngx_conf_t *cf, ngx_c shm_zone = NULL; burst = 0; - nodelay = 0; + delay = 0; for (i = 1; i < cf->args->nelts; i++) { @@ -915,8 +915,20 @@ ngx_http_limit_req(ngx_conf_t *cf, ngx_c continue; } + if (ngx_strncmp(value[i].data, "delay=", 6) == 0) { + + delay = ngx_atoi(value[i].data + 6, value[i].len - 6); + if (delay <= 0) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid delay value \"%V\"", &value[i]); + return NGX_CONF_ERROR; + } + + continue; + } + if (ngx_strcmp(value[i].data, "nodelay") == 0) { - nodelay = 1; + delay = NGX_MAX_INT_T_VALUE / 1000; continue; } @@ -956,7 +968,7 @@ ngx_http_limit_req(ngx_conf_t *cf, ngx_c limit->shm_zone = shm_zone; limit->burst = burst * 1000; - limit->nodelay = nodelay; + limit->delay = delay * 1000; return NGX_CONF_OK; }