Mercurial > hg > nginx-ranges
comparison src/http/modules/ngx_http_limit_req_module.c @ 427:ff86d646f9df NGINX_0_7_21
nginx 0.7.21
*) Changes in the ngx_http_limit_req_module.
*) Feature: the EXSLT support in the ngx_http_xslt_module.
Thanks to Denis F. Latypoff.
*) Workaround: compatibility with glibc 2.3.
Thanks to Eric Benson and Maxim Dounin.
*) Bugfix: nginx could not run on MacOSX 10.4 and earlier; the bug had
appeared in 0.7.6.
author | Igor Sysoev <http://sysoev.ru> |
---|---|
date | Tue, 11 Nov 2008 00:00:00 +0300 |
parents | b4f69f2ef02c |
children | ad0a34a8efa6 |
comparison
equal
deleted
inserted
replaced
426:735cec38a814 | 427:ff86d646f9df |
---|---|
31 | 31 |
32 | 32 |
33 typedef struct { | 33 typedef struct { |
34 ngx_shm_zone_t *shm_zone; | 34 ngx_shm_zone_t *shm_zone; |
35 float burst; | 35 float burst; |
36 ngx_msec_t delay; | 36 ngx_uint_t nodelay; /* unsigned nodelay:1 */ |
37 } ngx_http_limit_req_conf_t; | 37 } ngx_http_limit_req_conf_t; |
38 | 38 |
39 | 39 |
40 static void ngx_http_limit_req_delay(ngx_http_request_t *r); | 40 static void ngx_http_limit_req_delay(ngx_http_request_t *r); |
41 static ngx_int_t ngx_http_limit_req_lookup(ngx_http_limit_req_conf_t *lzcf, | 41 static ngx_int_t ngx_http_limit_req_lookup(ngx_http_limit_req_conf_t *lzcf, |
176 | 176 |
177 if (rc == NGX_BUSY) { | 177 if (rc == NGX_BUSY) { |
178 ngx_shmtx_unlock(&ctx->shpool->mutex); | 178 ngx_shmtx_unlock(&ctx->shpool->mutex); |
179 | 179 |
180 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | 180 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, |
181 "limiting requests, %.3f r/s", rate); | 181 "limiting requests, excess: %.3f", rate); |
182 | 182 |
183 return NGX_HTTP_SERVICE_UNAVAILABLE; | 183 return NGX_HTTP_SERVICE_UNAVAILABLE; |
184 } | 184 } |
185 | 185 |
186 if (rc == NGX_AGAIN) { | 186 if (rc == NGX_AGAIN) { |
187 ngx_shmtx_unlock(&ctx->shpool->mutex); | 187 ngx_shmtx_unlock(&ctx->shpool->mutex); |
188 | 188 |
189 if (lzcf->delay) { | 189 if (lzcf->nodelay) { |
190 ngx_log_error(NGX_LOG_WARN, r->connection->log, 0, | 190 return NGX_DECLINED; |
191 "delaying requests, %.3f r/s", rate); | 191 } |
192 | 192 |
193 if (ngx_handle_read_event(r->connection->read, 0) != NGX_OK) { | 193 ngx_log_error(NGX_LOG_WARN, r->connection->log, 0, |
194 return NGX_HTTP_INTERNAL_SERVER_ERROR; | 194 "delaying request, excess: %.3f", rate); |
195 } | 195 |
196 | 196 if (ngx_handle_read_event(r->connection->read, 0) != NGX_OK) { |
197 r->read_event_handler = ngx_http_test_reading; | 197 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
198 r->write_event_handler = ngx_http_limit_req_delay; | 198 } |
199 ngx_add_timer(r->connection->write, lzcf->delay); | 199 |
200 | 200 r->read_event_handler = ngx_http_test_reading; |
201 return NGX_AGAIN; | 201 r->write_event_handler = ngx_http_limit_req_delay; |
202 } | 202 ngx_add_timer(r->connection->write, (ngx_msec_t) (rate * 1000)); |
203 | 203 |
204 return NGX_DECLINED; | 204 return NGX_AGAIN; |
205 } | 205 } |
206 | 206 |
207 if (rc == NGX_OK) { | 207 if (rc == NGX_OK) { |
208 goto done; | 208 goto done; |
209 } | 209 } |
363 | 363 |
364 if (lz->rate > lzcf->burst) { | 364 if (lz->rate > lzcf->burst) { |
365 return NGX_BUSY; | 365 return NGX_BUSY; |
366 } | 366 } |
367 | 367 |
368 if (lz->rate > ctx->rate) { | 368 if (lz->rate > 0.0) { |
369 return NGX_AGAIN; | 369 return NGX_AGAIN; |
370 } | 370 } |
371 | 371 |
372 return NGX_OK; | 372 return NGX_OK; |
373 } | 373 } |
509 /* | 509 /* |
510 * set by ngx_pcalloc(): | 510 * set by ngx_pcalloc(): |
511 * | 511 * |
512 * conf->shm_zone = NULL; | 512 * conf->shm_zone = NULL; |
513 * conf->burst = 0.0; | 513 * conf->burst = 0.0; |
514 * conf->delay = 0; | 514 * conf->nodelay = 0; |
515 */ | 515 */ |
516 | 516 |
517 return conf; | 517 return conf; |
518 } | 518 } |
519 | 519 |
668 static char * | 668 static char * |
669 ngx_http_limit_req(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | 669 ngx_http_limit_req(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) |
670 { | 670 { |
671 ngx_http_limit_req_conf_t *lzcf = conf; | 671 ngx_http_limit_req_conf_t *lzcf = conf; |
672 | 672 |
673 u_char *p; | 673 ngx_int_t burst; |
674 size_t len; | 674 ngx_str_t *value, s; |
675 ngx_int_t burst, scale, delay; | 675 ngx_uint_t i; |
676 ngx_str_t *value, s; | |
677 ngx_uint_t i; | |
678 ngx_http_limit_req_ctx_t *ctx; | |
679 | 676 |
680 if (lzcf->shm_zone) { | 677 if (lzcf->shm_zone) { |
681 return "is duplicate"; | 678 return "is duplicate"; |
682 } | 679 } |
683 | 680 |
684 value = cf->args->elts; | 681 value = cf->args->elts; |
685 | 682 |
686 burst = 0; | 683 burst = 0; |
687 scale = 1; | |
688 delay = 0; | |
689 | 684 |
690 for (i = 1; i < cf->args->nelts; i++) { | 685 for (i = 1; i < cf->args->nelts; i++) { |
691 | 686 |
692 if (ngx_strncmp(value[i].data, "zone=", 5) == 0) { | 687 if (ngx_strncmp(value[i].data, "zone=", 5) == 0) { |
693 | 688 |
703 continue; | 698 continue; |
704 } | 699 } |
705 | 700 |
706 if (ngx_strncmp(value[i].data, "burst=", 6) == 0) { | 701 if (ngx_strncmp(value[i].data, "burst=", 6) == 0) { |
707 | 702 |
708 len = value[i].len; | 703 burst = ngx_atoi(value[i].data + 6, value[i].len - 6); |
709 p = value[i].data + len - 3; | |
710 | |
711 if (ngx_strncmp(p, "r/s", 3) == 0) { | |
712 scale = 1; | |
713 len -= 3; | |
714 | |
715 } else if (ngx_strncmp(p, "r/m", 3) == 0) { | |
716 scale = 60; | |
717 len -= 3; | |
718 } | |
719 | |
720 burst = ngx_atoi(value[i].data + 6, len - 6); | |
721 if (burst <= 0) { | 704 if (burst <= 0) { |
722 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | 705 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
723 "invalid burst rate \"%V\"", &value[i]); | 706 "invalid burst rate \"%V\"", &value[i]); |
724 return NGX_CONF_ERROR; | 707 return NGX_CONF_ERROR; |
725 } | 708 } |
726 | 709 |
727 continue; | 710 continue; |
728 } | 711 } |
729 | 712 |
730 if (ngx_strncmp(value[i].data, "delay=", 6) == 0) { | 713 if (ngx_strncmp(value[i].data, "nodelay", 7) == 0) { |
731 | 714 lzcf->nodelay = 1; |
732 s.len = value[i].len - 6; | |
733 s.data = value[i].data + 6; | |
734 | |
735 delay = ngx_parse_time(&s, 0); | |
736 if (delay < 0) { | |
737 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
738 "invalid clean_time value \"%V\"", &value[i]); | |
739 return NGX_CONF_ERROR; | |
740 } | |
741 | |
742 continue; | 715 continue; |
743 } | 716 } |
744 | 717 |
745 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | 718 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
746 "invalid parameter \"%V\"", &value[i]); | 719 "invalid parameter \"%V\"", &value[i]); |
759 "unknown limit_req_zone \"%V\"", | 732 "unknown limit_req_zone \"%V\"", |
760 &lzcf->shm_zone->name); | 733 &lzcf->shm_zone->name); |
761 return NGX_CONF_ERROR; | 734 return NGX_CONF_ERROR; |
762 } | 735 } |
763 | 736 |
764 if (burst) { | 737 lzcf->burst = (float) burst; |
765 lzcf->burst = (float) burst / scale; | |
766 | |
767 } else { | |
768 ctx = lzcf->shm_zone->data; | |
769 lzcf->burst = ctx->rate; | |
770 } | |
771 | |
772 lzcf->delay = (ngx_msec_t) delay; | |
773 | 738 |
774 return NGX_CONF_OK; | 739 return NGX_CONF_OK; |
775 } | 740 } |
776 | 741 |
777 | 742 |