Mercurial > hg > nginx
comparison src/http/modules/ngx_http_limit_req_module.c @ 7399:d6ca744c727e
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).
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Wed, 21 Nov 2018 18:56:50 +0300 |
parents | bca4dad0d3cb |
children | 2db68852d6a0 |
comparison
equal
deleted
inserted
replaced
7398:bca4dad0d3cb | 7399:d6ca744c727e |
---|---|
42 | 42 |
43 typedef struct { | 43 typedef struct { |
44 ngx_shm_zone_t *shm_zone; | 44 ngx_shm_zone_t *shm_zone; |
45 /* integer value, 1 corresponds to 0.001 r/s */ | 45 /* integer value, 1 corresponds to 0.001 r/s */ |
46 ngx_uint_t burst; | 46 ngx_uint_t burst; |
47 ngx_uint_t nodelay; /* unsigned nodelay:1 */ | 47 ngx_uint_t delay; |
48 } ngx_http_limit_req_limit_t; | 48 } ngx_http_limit_req_limit_t; |
49 | 49 |
50 | 50 |
51 typedef struct { | 51 typedef struct { |
52 ngx_array_t limits; | 52 ngx_array_t limits; |
497 ngx_http_limit_req_ctx_t *ctx; | 497 ngx_http_limit_req_ctx_t *ctx; |
498 ngx_http_limit_req_node_t *lr; | 498 ngx_http_limit_req_node_t *lr; |
499 | 499 |
500 excess = *ep; | 500 excess = *ep; |
501 | 501 |
502 if (excess == 0 || (*limit)->nodelay) { | 502 if ((ngx_uint_t) excess <= (*limit)->delay) { |
503 max_delay = 0; | 503 max_delay = 0; |
504 | 504 |
505 } else { | 505 } else { |
506 ctx = (*limit)->shm_zone->data; | 506 ctx = (*limit)->shm_zone->data; |
507 max_delay = excess * 1000 / ctx->rate; | 507 max_delay = (excess - (*limit)->delay) * 1000 / ctx->rate; |
508 } | 508 } |
509 | 509 |
510 while (n--) { | 510 while (n--) { |
511 ctx = limits[n].shm_zone->data; | 511 ctx = limits[n].shm_zone->data; |
512 lr = ctx->node; | 512 lr = ctx->node; |
542 | 542 |
543 ngx_shmtx_unlock(&ctx->shpool->mutex); | 543 ngx_shmtx_unlock(&ctx->shpool->mutex); |
544 | 544 |
545 ctx->node = NULL; | 545 ctx->node = NULL; |
546 | 546 |
547 if (limits[n].nodelay) { | 547 if ((ngx_uint_t) excess <= limits[n].delay) { |
548 continue; | 548 continue; |
549 } | 549 } |
550 | 550 |
551 delay = excess * 1000 / ctx->rate; | 551 delay = (excess - limits[n].delay) * 1000 / ctx->rate; |
552 | 552 |
553 if (delay > max_delay) { | 553 if (delay > max_delay) { |
554 max_delay = delay; | 554 max_delay = delay; |
555 *ep = excess; | 555 *ep = excess; |
556 *limit = &limits[n]; | 556 *limit = &limits[n]; |
873 static char * | 873 static char * |
874 ngx_http_limit_req(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | 874 ngx_http_limit_req(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) |
875 { | 875 { |
876 ngx_http_limit_req_conf_t *lrcf = conf; | 876 ngx_http_limit_req_conf_t *lrcf = conf; |
877 | 877 |
878 ngx_int_t burst; | 878 ngx_int_t burst, delay; |
879 ngx_str_t *value, s; | 879 ngx_str_t *value, s; |
880 ngx_uint_t i, nodelay; | 880 ngx_uint_t i; |
881 ngx_shm_zone_t *shm_zone; | 881 ngx_shm_zone_t *shm_zone; |
882 ngx_http_limit_req_limit_t *limit, *limits; | 882 ngx_http_limit_req_limit_t *limit, *limits; |
883 | 883 |
884 value = cf->args->elts; | 884 value = cf->args->elts; |
885 | 885 |
886 shm_zone = NULL; | 886 shm_zone = NULL; |
887 burst = 0; | 887 burst = 0; |
888 nodelay = 0; | 888 delay = 0; |
889 | 889 |
890 for (i = 1; i < cf->args->nelts; i++) { | 890 for (i = 1; i < cf->args->nelts; i++) { |
891 | 891 |
892 if (ngx_strncmp(value[i].data, "zone=", 5) == 0) { | 892 if (ngx_strncmp(value[i].data, "zone=", 5) == 0) { |
893 | 893 |
913 } | 913 } |
914 | 914 |
915 continue; | 915 continue; |
916 } | 916 } |
917 | 917 |
918 if (ngx_strncmp(value[i].data, "delay=", 6) == 0) { | |
919 | |
920 delay = ngx_atoi(value[i].data + 6, value[i].len - 6); | |
921 if (delay <= 0) { | |
922 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
923 "invalid delay value \"%V\"", &value[i]); | |
924 return NGX_CONF_ERROR; | |
925 } | |
926 | |
927 continue; | |
928 } | |
929 | |
918 if (ngx_strcmp(value[i].data, "nodelay") == 0) { | 930 if (ngx_strcmp(value[i].data, "nodelay") == 0) { |
919 nodelay = 1; | 931 delay = NGX_MAX_INT_T_VALUE / 1000; |
920 continue; | 932 continue; |
921 } | 933 } |
922 | 934 |
923 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | 935 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
924 "invalid parameter \"%V\"", &value[i]); | 936 "invalid parameter \"%V\"", &value[i]); |
954 return NGX_CONF_ERROR; | 966 return NGX_CONF_ERROR; |
955 } | 967 } |
956 | 968 |
957 limit->shm_zone = shm_zone; | 969 limit->shm_zone = shm_zone; |
958 limit->burst = burst * 1000; | 970 limit->burst = burst * 1000; |
959 limit->nodelay = nodelay; | 971 limit->delay = delay * 1000; |
960 | 972 |
961 return NGX_CONF_OK; | 973 return NGX_CONF_OK; |
962 } | 974 } |
963 | 975 |
964 | 976 |