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;