Mercurial > hg > nginx
comparison src/http/ngx_http_upstream_round_robin.c @ 4167:e917fc5eceb7 stable-1.0
Merging r4011, r4012, r4136:
Proxy related fixes:
*) Fixing cpu hog with all upstream servers marked "down".
The following configuration causes nginx to hog cpu due to infinite loop
in ngx_http_upstream_get_peer():
upstream backend {
server 127.0.0.1:8080 down;
server 127.0.0.1:8080 down;
}
server {
...
location / {
proxy_pass http://backend;
}
}
Make sure we don't loop infinitely in ngx_http_upstream_get_peer() but stop
after resetting peer weights once.
Return 0 if we are stuck. This is guaranteed to work as peer 0 always exists,
and eventually ngx_http_upstream_get_round_robin_peer() will do the right
thing falling back to backup servers or returning NGX_BUSY.
*) Upstream: properly allocate memory for tried flags.
Previous allocation only took into account number of non-backup servers, and
this caused memory corruption with many backup servers.
See report here:
http://mailman.nginx.org/pipermail/nginx/2011-May/026531.html
*) Fix of cpu hog in event pipe.
If client closed connection in ngx_event_pipe_write_to_downstream(), buffers
in the "out" chain were lost. This caused cpu hog if all available buffers
were in the "out" chain. Fix is to call ngx_chain_update_chains() before
checking return code of output filter to avoid loosing buffers in the "out"
chain.
Note that this situation (all available buffers in the "out" chain) isn't
normal, it should be prevented by busy buffers limit. Though right now it
may happen with complex protocols like fastcgi. This should be addressed
separately.
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Fri, 30 Sep 2011 14:30:01 +0000 |
parents | f87edc142316 |
children | 4919fb357a5d |
comparison
equal
deleted
inserted
replaced
4166:525a34d74a0a | 4167:e917fc5eceb7 |
---|---|
226 } | 226 } |
227 | 227 |
228 rrp->peers = us->peer.data; | 228 rrp->peers = us->peer.data; |
229 rrp->current = 0; | 229 rrp->current = 0; |
230 | 230 |
231 if (rrp->peers->number <= 8 * sizeof(uintptr_t)) { | 231 n = rrp->peers->number; |
232 | |
233 if (rrp->peers->next && rrp->peers->next->number > n) { | |
234 n = rrp->peers->next->number; | |
235 } | |
236 | |
237 if (n <= 8 * sizeof(uintptr_t)) { | |
232 rrp->tried = &rrp->data; | 238 rrp->tried = &rrp->data; |
233 rrp->data = 0; | 239 rrp->data = 0; |
234 | 240 |
235 } else { | 241 } else { |
236 n = (rrp->peers->number + (8 * sizeof(uintptr_t) - 1)) | 242 n = (n + (8 * sizeof(uintptr_t) - 1)) / (8 * sizeof(uintptr_t)); |
237 / (8 * sizeof(uintptr_t)); | |
238 | 243 |
239 rrp->tried = ngx_pcalloc(r->pool, n * sizeof(uintptr_t)); | 244 rrp->tried = ngx_pcalloc(r->pool, n * sizeof(uintptr_t)); |
240 if (rrp->tried == NULL) { | 245 if (rrp->tried == NULL) { |
241 return NGX_ERROR; | 246 return NGX_ERROR; |
242 } | 247 } |
583 | 588 |
584 | 589 |
585 static ngx_uint_t | 590 static ngx_uint_t |
586 ngx_http_upstream_get_peer(ngx_http_upstream_rr_peers_t *peers) | 591 ngx_http_upstream_get_peer(ngx_http_upstream_rr_peers_t *peers) |
587 { | 592 { |
588 ngx_uint_t i, n; | 593 ngx_uint_t i, n, reset = 0; |
589 ngx_http_upstream_rr_peer_t *peer; | 594 ngx_http_upstream_rr_peer_t *peer; |
590 | 595 |
591 peer = &peers->peer[0]; | 596 peer = &peers->peer[0]; |
592 | 597 |
593 for ( ;; ) { | 598 for ( ;; ) { |
622 } | 627 } |
623 | 628 |
624 return n; | 629 return n; |
625 } | 630 } |
626 | 631 |
632 if (reset++) { | |
633 return 0; | |
634 } | |
635 | |
627 for (i = 0; i < peers->number; i++) { | 636 for (i = 0; i < peers->number; i++) { |
628 peer[i].current_weight = peer[i].weight; | 637 peer[i].current_weight = peer[i].weight; |
629 } | 638 } |
630 } | 639 } |
631 } | 640 } |