Mercurial > hg > nginx
comparison src/http/ngx_http_upstream_round_robin.c @ 6100:c44459611d91
Upstream: store peers as a linked list.
This is an API change.
author | Ruslan Ermilov <ru@nginx.com> |
---|---|
date | Fri, 10 Apr 2015 14:48:36 +0300 |
parents | 6ff0ebd6fbf4 |
children | 3264b7828f72 |
comparison
equal
deleted
inserted
replaced
6099:6ff0ebd6fbf4 | 6100:c44459611d91 |
---|---|
32 ngx_http_upstream_srv_conf_t *us) | 32 ngx_http_upstream_srv_conf_t *us) |
33 { | 33 { |
34 ngx_url_t u; | 34 ngx_url_t u; |
35 ngx_uint_t i, j, n, w; | 35 ngx_uint_t i, j, n, w; |
36 ngx_http_upstream_server_t *server; | 36 ngx_http_upstream_server_t *server; |
37 ngx_http_upstream_rr_peer_t *peer; | 37 ngx_http_upstream_rr_peer_t *peer, **peerp; |
38 ngx_http_upstream_rr_peers_t *peers, *backup; | 38 ngx_http_upstream_rr_peers_t *peers, *backup; |
39 | 39 |
40 us->peer.init = ngx_http_upstream_init_round_robin_peer; | 40 us->peer.init = ngx_http_upstream_init_round_robin_peer; |
41 | 41 |
42 if (us->servers) { | 42 if (us->servers) { |
59 "no servers in upstream \"%V\" in %s:%ui", | 59 "no servers in upstream \"%V\" in %s:%ui", |
60 &us->host, us->file_name, us->line); | 60 &us->host, us->file_name, us->line); |
61 return NGX_ERROR; | 61 return NGX_ERROR; |
62 } | 62 } |
63 | 63 |
64 peers = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_rr_peers_t) | 64 peers = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_rr_peers_t)); |
65 + sizeof(ngx_http_upstream_rr_peer_t) * (n - 1)); | |
66 if (peers == NULL) { | 65 if (peers == NULL) { |
66 return NGX_ERROR; | |
67 } | |
68 | |
69 peer = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_rr_peer_t) * n); | |
70 if (peer == NULL) { | |
67 return NGX_ERROR; | 71 return NGX_ERROR; |
68 } | 72 } |
69 | 73 |
70 peers->single = (n == 1); | 74 peers->single = (n == 1); |
71 peers->number = n; | 75 peers->number = n; |
72 peers->weighted = (w != n); | 76 peers->weighted = (w != n); |
73 peers->total_weight = w; | 77 peers->total_weight = w; |
74 peers->name = &us->host; | 78 peers->name = &us->host; |
75 | 79 |
76 n = 0; | 80 n = 0; |
77 peer = peers->peer; | 81 peerp = &peers->peer; |
78 | 82 |
79 for (i = 0; i < us->servers->nelts; i++) { | 83 for (i = 0; i < us->servers->nelts; i++) { |
80 if (server[i].backup) { | 84 if (server[i].backup) { |
81 continue; | 85 continue; |
82 } | 86 } |
90 peer[n].current_weight = 0; | 94 peer[n].current_weight = 0; |
91 peer[n].max_fails = server[i].max_fails; | 95 peer[n].max_fails = server[i].max_fails; |
92 peer[n].fail_timeout = server[i].fail_timeout; | 96 peer[n].fail_timeout = server[i].fail_timeout; |
93 peer[n].down = server[i].down; | 97 peer[n].down = server[i].down; |
94 peer[n].server = server[i].name; | 98 peer[n].server = server[i].name; |
99 | |
100 *peerp = &peer[n]; | |
101 peerp = &peer[n].next; | |
95 n++; | 102 n++; |
96 } | 103 } |
97 } | 104 } |
98 | 105 |
99 us->peer.data = peers; | 106 us->peer.data = peers; |
114 | 121 |
115 if (n == 0) { | 122 if (n == 0) { |
116 return NGX_OK; | 123 return NGX_OK; |
117 } | 124 } |
118 | 125 |
119 backup = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_rr_peers_t) | 126 backup = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_rr_peers_t)); |
120 + sizeof(ngx_http_upstream_rr_peer_t) * (n - 1)); | |
121 if (backup == NULL) { | 127 if (backup == NULL) { |
128 return NGX_ERROR; | |
129 } | |
130 | |
131 peer = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_rr_peer_t) * n); | |
132 if (peer == NULL) { | |
122 return NGX_ERROR; | 133 return NGX_ERROR; |
123 } | 134 } |
124 | 135 |
125 peers->single = 0; | 136 peers->single = 0; |
126 backup->single = 0; | 137 backup->single = 0; |
128 backup->weighted = (w != n); | 139 backup->weighted = (w != n); |
129 backup->total_weight = w; | 140 backup->total_weight = w; |
130 backup->name = &us->host; | 141 backup->name = &us->host; |
131 | 142 |
132 n = 0; | 143 n = 0; |
133 peer = backup->peer; | 144 peerp = &backup->peer; |
134 | 145 |
135 for (i = 0; i < us->servers->nelts; i++) { | 146 for (i = 0; i < us->servers->nelts; i++) { |
136 if (!server[i].backup) { | 147 if (!server[i].backup) { |
137 continue; | 148 continue; |
138 } | 149 } |
146 peer[n].current_weight = 0; | 157 peer[n].current_weight = 0; |
147 peer[n].max_fails = server[i].max_fails; | 158 peer[n].max_fails = server[i].max_fails; |
148 peer[n].fail_timeout = server[i].fail_timeout; | 159 peer[n].fail_timeout = server[i].fail_timeout; |
149 peer[n].down = server[i].down; | 160 peer[n].down = server[i].down; |
150 peer[n].server = server[i].name; | 161 peer[n].server = server[i].name; |
162 | |
163 *peerp = &peer[n]; | |
164 peerp = &peer[n].next; | |
151 n++; | 165 n++; |
152 } | 166 } |
153 } | 167 } |
154 | 168 |
155 peers->next = backup; | 169 peers->next = backup; |
182 return NGX_ERROR; | 196 return NGX_ERROR; |
183 } | 197 } |
184 | 198 |
185 n = u.naddrs; | 199 n = u.naddrs; |
186 | 200 |
187 peers = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_rr_peers_t) | 201 peers = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_rr_peers_t)); |
188 + sizeof(ngx_http_upstream_rr_peer_t) * (n - 1)); | |
189 if (peers == NULL) { | 202 if (peers == NULL) { |
203 return NGX_ERROR; | |
204 } | |
205 | |
206 peer = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_rr_peer_t) * n); | |
207 if (peer == NULL) { | |
190 return NGX_ERROR; | 208 return NGX_ERROR; |
191 } | 209 } |
192 | 210 |
193 peers->single = (n == 1); | 211 peers->single = (n == 1); |
194 peers->number = n; | 212 peers->number = n; |
195 peers->weighted = 0; | 213 peers->weighted = 0; |
196 peers->total_weight = n; | 214 peers->total_weight = n; |
197 peers->name = &us->host; | 215 peers->name = &us->host; |
198 | 216 |
199 peer = peers->peer; | 217 peerp = &peers->peer; |
200 | 218 |
201 for (i = 0; i < u.naddrs; i++) { | 219 for (i = 0; i < u.naddrs; i++) { |
202 peer[i].sockaddr = u.addrs[i].sockaddr; | 220 peer[i].sockaddr = u.addrs[i].sockaddr; |
203 peer[i].socklen = u.addrs[i].socklen; | 221 peer[i].socklen = u.addrs[i].socklen; |
204 peer[i].name = u.addrs[i].name; | 222 peer[i].name = u.addrs[i].name; |
205 peer[i].weight = 1; | 223 peer[i].weight = 1; |
206 peer[i].effective_weight = 1; | 224 peer[i].effective_weight = 1; |
207 peer[i].current_weight = 0; | 225 peer[i].current_weight = 0; |
208 peer[i].max_fails = 1; | 226 peer[i].max_fails = 1; |
209 peer[i].fail_timeout = 10; | 227 peer[i].fail_timeout = 10; |
228 *peerp = &peer[i]; | |
229 peerp = &peer[i].next; | |
210 } | 230 } |
211 | 231 |
212 us->peer.data = peers; | 232 us->peer.data = peers; |
213 | 233 |
214 /* implicitly defined upstream has no backup servers */ | 234 /* implicitly defined upstream has no backup servers */ |
234 | 254 |
235 r->upstream->peer.data = rrp; | 255 r->upstream->peer.data = rrp; |
236 } | 256 } |
237 | 257 |
238 rrp->peers = us->peer.data; | 258 rrp->peers = us->peer.data; |
239 rrp->current = 0; | 259 rrp->current = NULL; |
240 | 260 |
241 n = rrp->peers->number; | 261 n = rrp->peers->number; |
242 | 262 |
243 if (rrp->peers->next && rrp->peers->next->number > n) { | 263 if (rrp->peers->next && rrp->peers->next->number > n) { |
244 n = rrp->peers->next->number; | 264 n = rrp->peers->next->number; |
278 u_char *p; | 298 u_char *p; |
279 size_t len; | 299 size_t len; |
280 socklen_t socklen; | 300 socklen_t socklen; |
281 ngx_uint_t i, n; | 301 ngx_uint_t i, n; |
282 struct sockaddr *sockaddr; | 302 struct sockaddr *sockaddr; |
283 ngx_http_upstream_rr_peer_t *peer; | 303 ngx_http_upstream_rr_peer_t *peer, **peerp; |
284 ngx_http_upstream_rr_peers_t *peers; | 304 ngx_http_upstream_rr_peers_t *peers; |
285 ngx_http_upstream_rr_peer_data_t *rrp; | 305 ngx_http_upstream_rr_peer_data_t *rrp; |
286 | 306 |
287 rrp = r->upstream->peer.data; | 307 rrp = r->upstream->peer.data; |
288 | 308 |
293 } | 313 } |
294 | 314 |
295 r->upstream->peer.data = rrp; | 315 r->upstream->peer.data = rrp; |
296 } | 316 } |
297 | 317 |
298 peers = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_rr_peers_t) | 318 peers = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_rr_peers_t)); |
299 + sizeof(ngx_http_upstream_rr_peer_t) * (ur->naddrs - 1)); | |
300 if (peers == NULL) { | 319 if (peers == NULL) { |
320 return NGX_ERROR; | |
321 } | |
322 | |
323 peer = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_rr_peer_t) | |
324 * ur->naddrs); | |
325 if (peer == NULL) { | |
301 return NGX_ERROR; | 326 return NGX_ERROR; |
302 } | 327 } |
303 | 328 |
304 peers->single = (ur->naddrs == 1); | 329 peers->single = (ur->naddrs == 1); |
305 peers->number = ur->naddrs; | 330 peers->number = ur->naddrs; |
306 peers->name = &ur->host; | 331 peers->name = &ur->host; |
307 | |
308 peer = peers->peer; | |
309 | 332 |
310 if (ur->sockaddr) { | 333 if (ur->sockaddr) { |
311 peer[0].sockaddr = ur->sockaddr; | 334 peer[0].sockaddr = ur->sockaddr; |
312 peer[0].socklen = ur->socklen; | 335 peer[0].socklen = ur->socklen; |
313 peer[0].name = ur->host; | 336 peer[0].name = ur->host; |
314 peer[0].weight = 1; | 337 peer[0].weight = 1; |
315 peer[0].effective_weight = 1; | 338 peer[0].effective_weight = 1; |
316 peer[0].current_weight = 0; | 339 peer[0].current_weight = 0; |
317 peer[0].max_fails = 1; | 340 peer[0].max_fails = 1; |
318 peer[0].fail_timeout = 10; | 341 peer[0].fail_timeout = 10; |
342 peers->peer = peer; | |
319 | 343 |
320 } else { | 344 } else { |
345 peerp = &peers->peer; | |
321 | 346 |
322 for (i = 0; i < ur->naddrs; i++) { | 347 for (i = 0; i < ur->naddrs; i++) { |
323 | 348 |
324 socklen = ur->addrs[i].socklen; | 349 socklen = ur->addrs[i].socklen; |
325 | 350 |
354 peer[i].weight = 1; | 379 peer[i].weight = 1; |
355 peer[i].effective_weight = 1; | 380 peer[i].effective_weight = 1; |
356 peer[i].current_weight = 0; | 381 peer[i].current_weight = 0; |
357 peer[i].max_fails = 1; | 382 peer[i].max_fails = 1; |
358 peer[i].fail_timeout = 10; | 383 peer[i].fail_timeout = 10; |
384 *peerp = &peer[i]; | |
385 peerp = &peer[i].next; | |
359 } | 386 } |
360 } | 387 } |
361 | 388 |
362 rrp->peers = peers; | 389 rrp->peers = peers; |
363 rrp->current = 0; | 390 rrp->current = NULL; |
364 | 391 |
365 if (rrp->peers->number <= 8 * sizeof(uintptr_t)) { | 392 if (rrp->peers->number <= 8 * sizeof(uintptr_t)) { |
366 rrp->tried = &rrp->data; | 393 rrp->tried = &rrp->data; |
367 rrp->data = 0; | 394 rrp->data = 0; |
368 | 395 |
407 peers = rrp->peers; | 434 peers = rrp->peers; |
408 | 435 |
409 /* ngx_lock_mutex(peers->mutex); */ | 436 /* ngx_lock_mutex(peers->mutex); */ |
410 | 437 |
411 if (peers->single) { | 438 if (peers->single) { |
412 peer = &peers->peer[0]; | 439 peer = peers->peer; |
413 | 440 |
414 if (peer->down) { | 441 if (peer->down) { |
415 goto failed; | 442 goto failed; |
416 } | 443 } |
417 | 444 |
445 rrp->current = peer; | |
446 | |
418 } else { | 447 } else { |
419 | 448 |
420 /* there are several peers */ | 449 /* there are several peers */ |
421 | 450 |
422 peer = ngx_http_upstream_get_peer(rrp); | 451 peer = ngx_http_upstream_get_peer(rrp); |
424 if (peer == NULL) { | 453 if (peer == NULL) { |
425 goto failed; | 454 goto failed; |
426 } | 455 } |
427 | 456 |
428 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0, | 457 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0, |
429 "get rr peer, current: %ui %i", | 458 "get rr peer, current: %p %i", |
430 rrp->current, peer->current_weight); | 459 peer, peer->current_weight); |
431 } | 460 } |
432 | 461 |
433 pc->sockaddr = peer->sockaddr; | 462 pc->sockaddr = peer->sockaddr; |
434 pc->socklen = peer->socklen; | 463 pc->socklen = peer->socklen; |
435 pc->name = &peer->name; | 464 pc->name = &peer->name; |
466 /* ngx_lock_mutex(peers->mutex); */ | 495 /* ngx_lock_mutex(peers->mutex); */ |
467 } | 496 } |
468 | 497 |
469 /* all peers failed, mark them as live for quick recovery */ | 498 /* all peers failed, mark them as live for quick recovery */ |
470 | 499 |
471 for (i = 0; i < peers->number; i++) { | 500 for (peer = peers->peer; peer; peer = peer->next) { |
472 peers->peer[i].fails = 0; | 501 peer->fails = 0; |
473 } | 502 } |
474 | 503 |
475 /* ngx_unlock_mutex(peers->mutex); */ | 504 /* ngx_unlock_mutex(peers->mutex); */ |
476 | 505 |
477 pc->name = peers->name; | 506 pc->name = peers->name; |
484 ngx_http_upstream_get_peer(ngx_http_upstream_rr_peer_data_t *rrp) | 513 ngx_http_upstream_get_peer(ngx_http_upstream_rr_peer_data_t *rrp) |
485 { | 514 { |
486 time_t now; | 515 time_t now; |
487 uintptr_t m; | 516 uintptr_t m; |
488 ngx_int_t total; | 517 ngx_int_t total; |
489 ngx_uint_t i, n; | 518 ngx_uint_t i, n, p; |
490 ngx_http_upstream_rr_peer_t *peer, *best; | 519 ngx_http_upstream_rr_peer_t *peer, *best; |
491 | 520 |
492 now = ngx_time(); | 521 now = ngx_time(); |
493 | 522 |
494 best = NULL; | 523 best = NULL; |
495 total = 0; | 524 total = 0; |
496 | 525 |
497 for (i = 0; i < rrp->peers->number; i++) { | 526 #if (NGX_SUPPRESS_WARN) |
527 p = 0; | |
528 #endif | |
529 | |
530 for (peer = rrp->peers->peer, i = 0; | |
531 peer; | |
532 peer = peer->next, i++) | |
533 { | |
498 | 534 |
499 n = i / (8 * sizeof(uintptr_t)); | 535 n = i / (8 * sizeof(uintptr_t)); |
500 m = (uintptr_t) 1 << i % (8 * sizeof(uintptr_t)); | 536 m = (uintptr_t) 1 << i % (8 * sizeof(uintptr_t)); |
501 | 537 |
502 if (rrp->tried[n] & m) { | 538 if (rrp->tried[n] & m) { |
503 continue; | 539 continue; |
504 } | 540 } |
505 | |
506 peer = &rrp->peers->peer[i]; | |
507 | 541 |
508 if (peer->down) { | 542 if (peer->down) { |
509 continue; | 543 continue; |
510 } | 544 } |
511 | 545 |
523 peer->effective_weight++; | 557 peer->effective_weight++; |
524 } | 558 } |
525 | 559 |
526 if (best == NULL || peer->current_weight > best->current_weight) { | 560 if (best == NULL || peer->current_weight > best->current_weight) { |
527 best = peer; | 561 best = peer; |
562 p = i; | |
528 } | 563 } |
529 } | 564 } |
530 | 565 |
531 if (best == NULL) { | 566 if (best == NULL) { |
532 return NULL; | 567 return NULL; |
533 } | 568 } |
534 | 569 |
535 i = best - &rrp->peers->peer[0]; | 570 rrp->current = best; |
536 | 571 |
537 rrp->current = i; | 572 n = p / (8 * sizeof(uintptr_t)); |
538 | 573 m = (uintptr_t) 1 << p % (8 * sizeof(uintptr_t)); |
539 n = i / (8 * sizeof(uintptr_t)); | |
540 m = (uintptr_t) 1 << i % (8 * sizeof(uintptr_t)); | |
541 | 574 |
542 rrp->tried[n] |= m; | 575 rrp->tried[n] |= m; |
543 | 576 |
544 best->current_weight -= total; | 577 best->current_weight -= total; |
545 | 578 |
563 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0, | 596 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0, |
564 "free rr peer %ui %ui", pc->tries, state); | 597 "free rr peer %ui %ui", pc->tries, state); |
565 | 598 |
566 /* TODO: NGX_PEER_KEEPALIVE */ | 599 /* TODO: NGX_PEER_KEEPALIVE */ |
567 | 600 |
568 peer = &rrp->peers->peer[rrp->current]; | 601 peer = rrp->current; |
569 | 602 |
570 if (rrp->peers->single) { | 603 if (rrp->peers->single) { |
571 | 604 |
572 peer->conns--; | 605 peer->conns--; |
573 | 606 |
587 if (peer->max_fails) { | 620 if (peer->max_fails) { |
588 peer->effective_weight -= peer->weight / peer->max_fails; | 621 peer->effective_weight -= peer->weight / peer->max_fails; |
589 } | 622 } |
590 | 623 |
591 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0, | 624 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0, |
592 "free rr peer failed: %ui %i", | 625 "free rr peer failed: %p %i", |
593 rrp->current, peer->effective_weight); | 626 peer, peer->effective_weight); |
594 | 627 |
595 if (peer->effective_weight < 0) { | 628 if (peer->effective_weight < 0) { |
596 peer->effective_weight = 0; | 629 peer->effective_weight = 0; |
597 } | 630 } |
598 | 631 |
627 | 660 |
628 ngx_int_t rc; | 661 ngx_int_t rc; |
629 ngx_ssl_session_t *ssl_session; | 662 ngx_ssl_session_t *ssl_session; |
630 ngx_http_upstream_rr_peer_t *peer; | 663 ngx_http_upstream_rr_peer_t *peer; |
631 | 664 |
632 peer = &rrp->peers->peer[rrp->current]; | 665 peer = rrp->current; |
633 | 666 |
634 /* TODO: threads only mutex */ | 667 /* TODO: threads only mutex */ |
635 /* ngx_lock_mutex(rrp->peers->mutex); */ | 668 /* ngx_lock_mutex(rrp->peers->mutex); */ |
636 | 669 |
637 ssl_session = peer->ssl_session; | 670 ssl_session = peer->ssl_session; |
663 } | 696 } |
664 | 697 |
665 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0, | 698 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0, |
666 "save session: %p", ssl_session); | 699 "save session: %p", ssl_session); |
667 | 700 |
668 peer = &rrp->peers->peer[rrp->current]; | 701 peer = rrp->current; |
669 | 702 |
670 /* TODO: threads only mutex */ | 703 /* TODO: threads only mutex */ |
671 /* ngx_lock_mutex(rrp->peers->mutex); */ | 704 /* ngx_lock_mutex(rrp->peers->mutex); */ |
672 | 705 |
673 old_ssl_session = peer->ssl_session; | 706 old_ssl_session = peer->ssl_session; |