mirror of
https://github.com/nginx/nginx.git
synced 2025-06-10 11:38:36 +08:00
Limit req: support for multiple "limit_req" limits.
This commit is contained in:
parent
73d0b6a721
commit
b06200f3dc
@ -18,6 +18,7 @@ typedef struct {
|
|||||||
ngx_msec_t last;
|
ngx_msec_t last;
|
||||||
/* integer value, 1 corresponds to 0.001 r/s */
|
/* integer value, 1 corresponds to 0.001 r/s */
|
||||||
ngx_uint_t excess;
|
ngx_uint_t excess;
|
||||||
|
ngx_uint_t count;
|
||||||
u_char data[1];
|
u_char data[1];
|
||||||
} ngx_http_limit_req_node_t;
|
} ngx_http_limit_req_node_t;
|
||||||
|
|
||||||
@ -36,6 +37,7 @@ typedef struct {
|
|||||||
ngx_uint_t rate;
|
ngx_uint_t rate;
|
||||||
ngx_int_t index;
|
ngx_int_t index;
|
||||||
ngx_str_t var;
|
ngx_str_t var;
|
||||||
|
ngx_http_limit_req_node_t *node;
|
||||||
} ngx_http_limit_req_ctx_t;
|
} ngx_http_limit_req_ctx_t;
|
||||||
|
|
||||||
|
|
||||||
@ -43,16 +45,23 @@ typedef struct {
|
|||||||
ngx_shm_zone_t *shm_zone;
|
ngx_shm_zone_t *shm_zone;
|
||||||
/* integer value, 1 corresponds to 0.001 r/s */
|
/* integer value, 1 corresponds to 0.001 r/s */
|
||||||
ngx_uint_t burst;
|
ngx_uint_t burst;
|
||||||
|
ngx_uint_t nodelay; /* unsigned nodelay:1 */
|
||||||
|
} ngx_http_limit_req_limit_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ngx_array_t limits;
|
||||||
ngx_uint_t limit_log_level;
|
ngx_uint_t limit_log_level;
|
||||||
ngx_uint_t delay_log_level;
|
ngx_uint_t delay_log_level;
|
||||||
|
|
||||||
ngx_uint_t nodelay; /* unsigned nodelay:1 */
|
|
||||||
} ngx_http_limit_req_conf_t;
|
} ngx_http_limit_req_conf_t;
|
||||||
|
|
||||||
|
|
||||||
static void ngx_http_limit_req_delay(ngx_http_request_t *r);
|
static void ngx_http_limit_req_delay(ngx_http_request_t *r);
|
||||||
static ngx_int_t ngx_http_limit_req_lookup(ngx_http_limit_req_conf_t *lrcf,
|
static ngx_int_t ngx_http_limit_req_lookup(ngx_http_limit_req_limit_t *limit,
|
||||||
ngx_uint_t hash, u_char *data, size_t len, ngx_uint_t *ep);
|
ngx_uint_t hash, u_char *data, size_t len, ngx_uint_t *ep,
|
||||||
|
ngx_uint_t account);
|
||||||
|
static ngx_msec_t ngx_http_limit_req_account(ngx_http_limit_req_limit_t *limits,
|
||||||
|
ngx_uint_t n, ngx_uint_t *ep, ngx_http_limit_req_limit_t **limit);
|
||||||
static void ngx_http_limit_req_expire(ngx_http_limit_req_ctx_t *ctx,
|
static void ngx_http_limit_req_expire(ngx_http_limit_req_ctx_t *ctx,
|
||||||
ngx_uint_t n);
|
ngx_uint_t n);
|
||||||
|
|
||||||
@ -139,33 +148,40 @@ ngx_http_limit_req_handler(ngx_http_request_t *r)
|
|||||||
size_t len;
|
size_t len;
|
||||||
uint32_t hash;
|
uint32_t hash;
|
||||||
ngx_int_t rc;
|
ngx_int_t rc;
|
||||||
ngx_uint_t excess;
|
ngx_uint_t n, excess;
|
||||||
|
ngx_msec_t delay;
|
||||||
ngx_http_variable_value_t *vv;
|
ngx_http_variable_value_t *vv;
|
||||||
ngx_http_limit_req_ctx_t *ctx;
|
ngx_http_limit_req_ctx_t *ctx;
|
||||||
ngx_http_limit_req_conf_t *lrcf;
|
ngx_http_limit_req_conf_t *lrcf;
|
||||||
|
ngx_http_limit_req_limit_t *limit, *limits;
|
||||||
|
|
||||||
if (r->main->limit_req_set) {
|
if (r->main->limit_req_set) {
|
||||||
return NGX_DECLINED;
|
return NGX_DECLINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
lrcf = ngx_http_get_module_loc_conf(r, ngx_http_limit_req_module);
|
lrcf = ngx_http_get_module_loc_conf(r, ngx_http_limit_req_module);
|
||||||
|
limits = lrcf->limits.elts;
|
||||||
|
|
||||||
if (lrcf->shm_zone == NULL) {
|
excess = 0;
|
||||||
return NGX_DECLINED;
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx = lrcf->shm_zone->data;
|
rc = NGX_DECLINED;
|
||||||
|
|
||||||
|
for (n = 0; n < lrcf->limits.nelts; n++) {
|
||||||
|
|
||||||
|
limit = &limits[n];
|
||||||
|
|
||||||
|
ctx = limit->shm_zone->data;
|
||||||
|
|
||||||
vv = ngx_http_get_indexed_variable(r, ctx->index);
|
vv = ngx_http_get_indexed_variable(r, ctx->index);
|
||||||
|
|
||||||
if (vv == NULL || vv->not_found) {
|
if (vv == NULL || vv->not_found) {
|
||||||
return NGX_DECLINED;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
len = vv->len;
|
len = vv->len;
|
||||||
|
|
||||||
if (len == 0) {
|
if (len == 0) {
|
||||||
return NGX_DECLINED;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (len > 65535) {
|
if (len > 65535) {
|
||||||
@ -173,47 +189,76 @@ ngx_http_limit_req_handler(ngx_http_request_t *r)
|
|||||||
"the value of the \"%V\" variable "
|
"the value of the \"%V\" variable "
|
||||||
"is more than 65535 bytes: \"%v\"",
|
"is more than 65535 bytes: \"%v\"",
|
||||||
&ctx->var, vv);
|
&ctx->var, vv);
|
||||||
return NGX_DECLINED;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
r->main->limit_req_set = 1;
|
|
||||||
|
|
||||||
hash = ngx_crc32_short(vv->data, len);
|
hash = ngx_crc32_short(vv->data, len);
|
||||||
|
|
||||||
ngx_shmtx_lock(&ctx->shpool->mutex);
|
ngx_shmtx_lock(&ctx->shpool->mutex);
|
||||||
|
|
||||||
rc = ngx_http_limit_req_lookup(lrcf, hash, vv->data, len, &excess);
|
rc = ngx_http_limit_req_lookup(limit, hash, vv->data, len, &excess,
|
||||||
|
(n == lrcf->limits.nelts - 1));
|
||||||
|
|
||||||
ngx_shmtx_unlock(&ctx->shpool->mutex);
|
ngx_shmtx_unlock(&ctx->shpool->mutex);
|
||||||
|
|
||||||
ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||||
"limit_req: %i %ui.%03ui", rc, excess / 1000, excess % 1000);
|
"limit_req[%ui]: %i %ui.%03ui",
|
||||||
|
n, rc, excess / 1000, excess % 1000);
|
||||||
|
|
||||||
if (rc == NGX_OK) {
|
if (rc != NGX_AGAIN) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rc == NGX_DECLINED) {
|
||||||
return NGX_DECLINED;
|
return NGX_DECLINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
r->main->limit_req_set = 1;
|
||||||
|
|
||||||
if (rc == NGX_BUSY || rc == NGX_ERROR) {
|
if (rc == NGX_BUSY || rc == NGX_ERROR) {
|
||||||
|
|
||||||
if (rc == NGX_BUSY) {
|
if (rc == NGX_BUSY) {
|
||||||
ngx_log_error(lrcf->limit_log_level, r->connection->log, 0,
|
ngx_log_error(lrcf->limit_log_level, r->connection->log, 0,
|
||||||
"limiting requests, excess: %ui.%03ui by zone \"%V\"",
|
"limiting requests, excess: %ui.%03ui by zone \"%V\"",
|
||||||
excess / 1000, excess % 1000,
|
excess / 1000, excess % 1000,
|
||||||
&lrcf->shm_zone->shm.name);
|
&limit->shm_zone->shm.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (n--) {
|
||||||
|
ctx = limits[n].shm_zone->data;
|
||||||
|
|
||||||
|
if (ctx->node == NULL) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_shmtx_lock(&ctx->shpool->mutex);
|
||||||
|
|
||||||
|
ctx->node->count--;
|
||||||
|
|
||||||
|
ngx_shmtx_unlock(&ctx->shpool->mutex);
|
||||||
|
|
||||||
|
ctx->node = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NGX_HTTP_SERVICE_UNAVAILABLE;
|
return NGX_HTTP_SERVICE_UNAVAILABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* rc == NGX_AGAIN */
|
/* rc == NGX_AGAIN || rc == NGX_OK */
|
||||||
|
|
||||||
if (lrcf->nodelay) {
|
if (rc == NGX_AGAIN) {
|
||||||
|
excess = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
delay = ngx_http_limit_req_account(limits, n, &excess, &limit);
|
||||||
|
|
||||||
|
if (!delay) {
|
||||||
return NGX_DECLINED;
|
return NGX_DECLINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
ngx_log_error(lrcf->delay_log_level, r->connection->log, 0,
|
ngx_log_error(lrcf->delay_log_level, r->connection->log, 0,
|
||||||
"delaying request, excess: %ui.%03ui, by zone \"%V\"",
|
"delaying request, excess: %ui.%03ui, by zone \"%V\"",
|
||||||
excess / 1000, excess % 1000, &lrcf->shm_zone->shm.name);
|
excess / 1000, excess % 1000, &limit->shm_zone->shm.name);
|
||||||
|
|
||||||
if (ngx_handle_read_event(r->connection->read, 0) != NGX_OK) {
|
if (ngx_handle_read_event(r->connection->read, 0) != NGX_OK) {
|
||||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||||
@ -221,8 +266,7 @@ ngx_http_limit_req_handler(ngx_http_request_t *r)
|
|||||||
|
|
||||||
r->read_event_handler = ngx_http_test_reading;
|
r->read_event_handler = ngx_http_test_reading;
|
||||||
r->write_event_handler = ngx_http_limit_req_delay;
|
r->write_event_handler = ngx_http_limit_req_delay;
|
||||||
ngx_add_timer(r->connection->write,
|
ngx_add_timer(r->connection->write, delay);
|
||||||
(ngx_msec_t) excess * 1000 / ctx->rate);
|
|
||||||
|
|
||||||
return NGX_AGAIN;
|
return NGX_AGAIN;
|
||||||
}
|
}
|
||||||
@ -303,8 +347,8 @@ ngx_http_limit_req_rbtree_insert_value(ngx_rbtree_node_t *temp,
|
|||||||
|
|
||||||
|
|
||||||
static ngx_int_t
|
static ngx_int_t
|
||||||
ngx_http_limit_req_lookup(ngx_http_limit_req_conf_t *lrcf, ngx_uint_t hash,
|
ngx_http_limit_req_lookup(ngx_http_limit_req_limit_t *limit, ngx_uint_t hash,
|
||||||
u_char *data, size_t len, ngx_uint_t *ep)
|
u_char *data, size_t len, ngx_uint_t *ep, ngx_uint_t account)
|
||||||
{
|
{
|
||||||
size_t size;
|
size_t size;
|
||||||
ngx_int_t rc, excess;
|
ngx_int_t rc, excess;
|
||||||
@ -318,7 +362,7 @@ ngx_http_limit_req_lookup(ngx_http_limit_req_conf_t *lrcf, ngx_uint_t hash,
|
|||||||
tp = ngx_timeofday();
|
tp = ngx_timeofday();
|
||||||
now = (ngx_msec_t) (tp->sec * 1000 + tp->msec);
|
now = (ngx_msec_t) (tp->sec * 1000 + tp->msec);
|
||||||
|
|
||||||
ctx = lrcf->shm_zone->data;
|
ctx = limit->shm_zone->data;
|
||||||
|
|
||||||
node = ctx->sh->rbtree.root;
|
node = ctx->sh->rbtree.root;
|
||||||
sentinel = ctx->sh->rbtree.sentinel;
|
sentinel = ctx->sh->rbtree.sentinel;
|
||||||
@ -356,18 +400,21 @@ ngx_http_limit_req_lookup(ngx_http_limit_req_conf_t *lrcf, ngx_uint_t hash,
|
|||||||
|
|
||||||
*ep = excess;
|
*ep = excess;
|
||||||
|
|
||||||
if ((ngx_uint_t) excess > lrcf->burst) {
|
if ((ngx_uint_t) excess > limit->burst) {
|
||||||
return NGX_BUSY;
|
return NGX_BUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (account) {
|
||||||
lr->excess = excess;
|
lr->excess = excess;
|
||||||
lr->last = now;
|
lr->last = now;
|
||||||
|
return NGX_OK;
|
||||||
if (excess) {
|
|
||||||
return NGX_AGAIN;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return NGX_OK;
|
lr->count++;
|
||||||
|
|
||||||
|
ctx->node = lr;
|
||||||
|
|
||||||
|
return NGX_AGAIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
node = (rc < 0) ? node->left : node->right;
|
node = (rc < 0) ? node->left : node->right;
|
||||||
@ -406,13 +453,90 @@ ngx_http_limit_req_lookup(ngx_http_limit_req_conf_t *lrcf, ngx_uint_t hash,
|
|||||||
|
|
||||||
lr->len = (u_char) len;
|
lr->len = (u_char) len;
|
||||||
lr->excess = 0;
|
lr->excess = 0;
|
||||||
lr->last = now;
|
|
||||||
|
|
||||||
ngx_memcpy(lr->data, data, len);
|
ngx_memcpy(lr->data, data, len);
|
||||||
|
|
||||||
|
if (account) {
|
||||||
|
lr->last = now;
|
||||||
|
lr->count = 0;
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lr->last = 0;
|
||||||
|
lr->count = 1;
|
||||||
|
|
||||||
|
ctx->node = lr;
|
||||||
|
|
||||||
|
return NGX_AGAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_msec_t
|
||||||
|
ngx_http_limit_req_account(ngx_http_limit_req_limit_t *limits, ngx_uint_t n,
|
||||||
|
ngx_uint_t *ep, ngx_http_limit_req_limit_t **limit)
|
||||||
|
{
|
||||||
|
ngx_int_t excess;
|
||||||
|
ngx_time_t *tp;
|
||||||
|
ngx_msec_t now, delay, max_delay;
|
||||||
|
ngx_msec_int_t ms;
|
||||||
|
ngx_http_limit_req_ctx_t *ctx;
|
||||||
|
ngx_http_limit_req_node_t *lr;
|
||||||
|
|
||||||
|
excess = *ep;
|
||||||
|
|
||||||
|
if (excess == 0 || (*limit)->nodelay) {
|
||||||
|
max_delay = 0;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
ctx = (*limit)->shm_zone->data;
|
||||||
|
max_delay = excess * 1000 / ctx->rate;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (n--) {
|
||||||
|
ctx = limits[n].shm_zone->data;
|
||||||
|
lr = ctx->node;
|
||||||
|
|
||||||
|
if (lr == NULL) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_shmtx_lock(&ctx->shpool->mutex);
|
||||||
|
|
||||||
|
tp = ngx_timeofday();
|
||||||
|
|
||||||
|
now = (ngx_msec_t) (tp->sec * 1000 + tp->msec);
|
||||||
|
ms = (ngx_msec_int_t) (now - lr->last);
|
||||||
|
|
||||||
|
excess = lr->excess - ctx->rate * ngx_abs(ms) / 1000 + 1000;
|
||||||
|
|
||||||
|
if (excess < 0) {
|
||||||
|
excess = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
lr->last = now;
|
||||||
|
lr->excess = excess;
|
||||||
|
lr->count--;
|
||||||
|
|
||||||
|
ngx_shmtx_unlock(&ctx->shpool->mutex);
|
||||||
|
|
||||||
|
ctx->node = NULL;
|
||||||
|
|
||||||
|
if (limits[n].nodelay) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
delay = excess * 1000 / ctx->rate;
|
||||||
|
|
||||||
|
if (delay > max_delay) {
|
||||||
|
max_delay = delay;
|
||||||
|
*ep = excess;
|
||||||
|
*limit = &limits[n];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return max_delay;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ngx_http_limit_req_expire(ngx_http_limit_req_ctx_t *ctx, ngx_uint_t n)
|
ngx_http_limit_req_expire(ngx_http_limit_req_ctx_t *ctx, ngx_uint_t n)
|
||||||
@ -445,6 +569,16 @@ ngx_http_limit_req_expire(ngx_http_limit_req_ctx_t *ctx, ngx_uint_t n)
|
|||||||
|
|
||||||
lr = ngx_queue_data(q, ngx_http_limit_req_node_t, queue);
|
lr = ngx_queue_data(q, ngx_http_limit_req_node_t, queue);
|
||||||
|
|
||||||
|
if (lr->count) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* There is not much sense in looking further,
|
||||||
|
* because we bump nodes on the lookup stage.
|
||||||
|
*/
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (n++ != 0) {
|
if (n++ != 0) {
|
||||||
|
|
||||||
ms = (ngx_msec_int_t) (now - lr->last);
|
ms = (ngx_msec_int_t) (now - lr->last);
|
||||||
@ -545,9 +679,7 @@ ngx_http_limit_req_create_conf(ngx_conf_t *cf)
|
|||||||
/*
|
/*
|
||||||
* set by ngx_pcalloc():
|
* set by ngx_pcalloc():
|
||||||
*
|
*
|
||||||
* conf->shm_zone = NULL;
|
* conf->limits.elts = NULL;
|
||||||
* conf->burst = 0;
|
|
||||||
* conf->nodelay = 0;
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
conf->limit_log_level = NGX_CONF_UNSET_UINT;
|
conf->limit_log_level = NGX_CONF_UNSET_UINT;
|
||||||
@ -562,10 +694,8 @@ ngx_http_limit_req_merge_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||||||
ngx_http_limit_req_conf_t *prev = parent;
|
ngx_http_limit_req_conf_t *prev = parent;
|
||||||
ngx_http_limit_req_conf_t *conf = child;
|
ngx_http_limit_req_conf_t *conf = child;
|
||||||
|
|
||||||
if (conf->shm_zone == NULL) {
|
if (conf->limits.elts == NULL) {
|
||||||
conf->shm_zone = prev->shm_zone;
|
conf->limits = prev->limits;
|
||||||
conf->burst = prev->burst;
|
|
||||||
conf->nodelay = prev->nodelay;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ngx_conf_merge_uint_value(conf->limit_log_level, prev->limit_log_level,
|
ngx_conf_merge_uint_value(conf->limit_log_level, prev->limit_log_level,
|
||||||
@ -728,15 +858,15 @@ ngx_http_limit_req(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||||||
|
|
||||||
ngx_int_t burst;
|
ngx_int_t burst;
|
||||||
ngx_str_t *value, s;
|
ngx_str_t *value, s;
|
||||||
ngx_uint_t i;
|
ngx_uint_t i, nodelay;
|
||||||
|
ngx_shm_zone_t *shm_zone;
|
||||||
if (lrcf->shm_zone) {
|
ngx_http_limit_req_limit_t *limit, *limits;
|
||||||
return "is duplicate";
|
|
||||||
}
|
|
||||||
|
|
||||||
value = cf->args->elts;
|
value = cf->args->elts;
|
||||||
|
|
||||||
|
shm_zone = NULL;
|
||||||
burst = 0;
|
burst = 0;
|
||||||
|
nodelay = 0;
|
||||||
|
|
||||||
for (i = 1; i < cf->args->nelts; i++) {
|
for (i = 1; i < cf->args->nelts; i++) {
|
||||||
|
|
||||||
@ -745,9 +875,9 @@ ngx_http_limit_req(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||||||
s.len = value[i].len - 5;
|
s.len = value[i].len - 5;
|
||||||
s.data = value[i].data + 5;
|
s.data = value[i].data + 5;
|
||||||
|
|
||||||
lrcf->shm_zone = ngx_shared_memory_add(cf, &s, 0,
|
shm_zone = ngx_shared_memory_add(cf, &s, 0,
|
||||||
&ngx_http_limit_req_module);
|
&ngx_http_limit_req_module);
|
||||||
if (lrcf->shm_zone == NULL) {
|
if (shm_zone == NULL) {
|
||||||
return NGX_CONF_ERROR;
|
return NGX_CONF_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -767,7 +897,7 @@ ngx_http_limit_req(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ngx_strncmp(value[i].data, "nodelay", 7) == 0) {
|
if (ngx_strncmp(value[i].data, "nodelay", 7) == 0) {
|
||||||
lrcf->nodelay = 1;
|
nodelay = 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -776,21 +906,42 @@ ngx_http_limit_req(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||||||
return NGX_CONF_ERROR;
|
return NGX_CONF_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lrcf->shm_zone == NULL) {
|
if (shm_zone == NULL) {
|
||||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||||
"\"%V\" must have \"zone\" parameter",
|
"\"%V\" must have \"zone\" parameter",
|
||||||
&cmd->name);
|
&cmd->name);
|
||||||
return NGX_CONF_ERROR;
|
return NGX_CONF_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lrcf->shm_zone->data == NULL) {
|
if (shm_zone->data == NULL) {
|
||||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||||
"unknown limit_req_zone \"%V\"",
|
"unknown limit_req_zone \"%V\"",
|
||||||
&lrcf->shm_zone->shm.name);
|
&shm_zone->shm.name);
|
||||||
return NGX_CONF_ERROR;
|
return NGX_CONF_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
lrcf->burst = burst * 1000;
|
limits = lrcf->limits.elts;
|
||||||
|
|
||||||
|
if (limits == NULL) {
|
||||||
|
if (ngx_array_init(&lrcf->limits, cf->pool, 1,
|
||||||
|
sizeof(ngx_http_limit_req_limit_t))
|
||||||
|
!= NGX_OK)
|
||||||
|
{
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < lrcf->limits.nelts; i++) {
|
||||||
|
if (shm_zone == limits[i].shm_zone) {
|
||||||
|
return "is duplicate";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
limit = ngx_array_push(&lrcf->limits);
|
||||||
|
|
||||||
|
limit->shm_zone = shm_zone;
|
||||||
|
limit->burst = burst * 1000;
|
||||||
|
limit->nodelay = nodelay;
|
||||||
|
|
||||||
return NGX_CONF_OK;
|
return NGX_CONF_OK;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user