12
12
13
13
static ngx_int_t ngx_http_upstream_cmp_servers(const void *one,
14
14
const void *two);
15
-static ngx_uint_t
16
-ngx_http_upstream_get_peer(ngx_http_upstream_rr_peers_t *peers);
15
+static ngx_http_upstream_rr_peer_t *ngx_http_upstream_get_peer(
16
+ ngx_http_upstream_rr_peer_data_t *rrp);
17
17
18
18
#if (NGX_HTTP_SSL)
19
19
@@ -81,7 +81,8 @@ ngx_http_upstream_init_round_robin(ngx_conf_t *cf,
81
81
peers->peer[n].fail_timeout = server[i].fail_timeout;
82
82
peers->peer[n].down = server[i].down;
83
83
peers->peer[n].weight = server[i].down ? 0 : server[i].weight;
84
- peers->peer[n].current_weight = peers->peer[n].weight;
84
+ peers->peer[n].effective_weight = peers->peer[n].weight;
85
+ peers->peer[n].current_weight = 0;
85
86
n++;
86
87
}
87
88
}
@@ -131,7 +132,8 @@ ngx_http_upstream_init_round_robin(ngx_conf_t *cf,
131
132
backup->peer[n].socklen = server[i].addrs[j].socklen;
132
133
backup->peer[n].name = server[i].addrs[j].name;
133
134
backup->peer[n].weight = server[i].weight;
134
- backup->peer[n].current_weight = server[i].weight;
135
+ backup->peer[n].effective_weight = server[i].weight;
136
+ backup->peer[n].current_weight = 0;
135
137
backup->peer[n].max_fails = server[i].max_fails;
136
138
backup->peer[n].fail_timeout = server[i].fail_timeout;
137
139
backup->peer[n].down = server[i].down;
@@ -190,7 +192,8 @@ ngx_http_upstream_init_round_robin(ngx_conf_t *cf,
190
192
peers->peer[i].socklen = u.addrs[i].socklen;
191
193
peers->peer[i].name = u.addrs[i].name;
192
194
peers->peer[i].weight = 1;
193
- peers->peer[i].current_weight = 1;
195
+ peers->peer[i].effective_weight = 1;
196
+ peers->peer[i].current_weight = 0;
194
197
peers->peer[i].max_fails = 1;
195
198
peers->peer[i].fail_timeout = 10;
196
199
}
@@ -306,7 +309,8 @@ ngx_http_upstream_create_round_robin_peer(ngx_http_request_t *r,
306
309
peers->peer[0].socklen = ur->socklen;
307
310
peers->peer[0].name = ur->host;
308
311
peers->peer[0].weight = 1;
309
- peers->peer[0].current_weight = 1;
312
+ peers->peer[0].effective_weight = 1;
313
+ peers->peer[0].current_weight = 0;
310
314
peers->peer[0].max_fails = 1;
311
315
peers->peer[0].fail_timeout = 10;
312
316
@@ -338,7 +342,8 @@ ngx_http_upstream_create_round_robin_peer(ngx_http_request_t *r,
338
342
peers->peer[i].name.len = len;
339
343
peers->peer[i].name.data = p;
340
344
peers->peer[i].weight = 1;
341
- peers->peer[i].current_weight = 1;
345
+ peers->peer[i].effective_weight = 1;
346
+ peers->peer[i].current_weight = 0;
342
347
peers->peer[i].max_fails = 1;
343
348
peers->peer[i].fail_timeout = 10;
344
349
}
@@ -378,8 +383,6 @@ ngx_http_upstream_get_round_robin_peer(ngx_peer_connection_t *pc, void *data)
378
383
{
379
384
ngx_http_upstream_rr_peer_data_t *rrp = data;
380
385
381
- time_t now;
382
- uintptr_t m;
383
386
ngx_int_t rc;
384
387
ngx_uint_t i, n;
385
388
ngx_connection_t *c;
@@ -389,8 +392,6 @@ ngx_http_upstream_get_round_robin_peer(ngx_peer_connection_t *pc, void *data)
389
392
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0,
390
393
"get rr peer, try: %ui", pc->tries);
391
394
392
- now = ngx_time();
393
-
394
395
/* ngx_lock_mutex(rrp->peers->mutex); */
395
396
396
397
if (rrp->peers->last_cached) {
@@ -423,118 +424,15 @@ ngx_http_upstream_get_round_robin_peer(ngx_peer_connection_t *pc, void *data)
423
424
424
425
/* there are several peers */
425
426
426
- if (pc->tries == rrp->peers->number) {
427
-
428
- /* it's a first try - get a current peer */
429
-
430
- i = pc->tries;
431
-
432
- for ( ;; ) {
433
- rrp->current = ngx_http_upstream_get_peer(rrp->peers);
434
-
435
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0,
436
- "get rr peer, current: %ui %i",
437
- rrp->current,
438
- rrp->peers->peer[rrp->current].current_weight);
439
-
440
- n = rrp->current / (8 * sizeof(uintptr_t));
441
- m = (uintptr_t) 1 << rrp->current % (8 * sizeof(uintptr_t));
442
-
443
- if (!(rrp->tried[n] & m)) {
444
- peer = &rrp->peers->peer[rrp->current];
445
-
446
- if (!peer->down) {
447
-
448
- if (peer->max_fails == 0
449
- || peer->fails < peer->max_fails)
450
- {
451
- break;
452
- }
427
+ peer = ngx_http_upstream_get_peer(rrp);
453
428
454
- if (now - peer->checked > peer->fail_timeout) {
455
- peer->checked = now;
456
- break;
457
- }
458
-
459
- peer->current_weight = 0;
460
-
461
- } else {
462
- rrp->tried[n] |= m;
463
- }
464
-
465
- pc->tries--;
466
- }
467
-
468
- if (pc->tries == 0) {
469
- goto failed;
470
- }
471
-
472
- if (--i == 0) {
473
- ngx_log_error(NGX_LOG_ALERT, pc->log, 0,
474
- "round robin upstream stuck on %ui tries",
475
- pc->tries);
476
- goto failed;
477
- }
478
- }
479
-
480
- peer->current_weight--;
481
-
482
- } else {
483
-
484
- i = pc->tries;
485
-
486
- for ( ;; ) {
487
- n = rrp->current / (8 * sizeof(uintptr_t));
488
- m = (uintptr_t) 1 << rrp->current % (8 * sizeof(uintptr_t));
489
-
490
- if (!(rrp->tried[n] & m)) {
491
-
492
- peer = &rrp->peers->peer[rrp->current];
493
-
494
- if (!peer->down) {
495
-
496
- if (peer->max_fails == 0
497
- || peer->fails < peer->max_fails)
498
- {
499
- break;
500
- }
501
-
502
- if (now - peer->checked > peer->fail_timeout) {
503
- peer->checked = now;
504
- break;
505
- }
506
-
507
- peer->current_weight = 0;
508
-
509
- } else {
510
- rrp->tried[n] |= m;
511
- }
512
-
513
- pc->tries--;
514
- }
515
-
516
- rrp->current++;
517
-
518
- if (rrp->current >= rrp->peers->number) {
519
- rrp->current = 0;
520
- }
521
-
522
- if (pc->tries == 0) {
523
- goto failed;
524
- }
525
-
526
- if (--i == 0) {
527
- ngx_log_error(NGX_LOG_ALERT, pc->log, 0,
528
- "round robin upstream stuck on %ui tries",
529
- pc->tries);
530
- goto failed;
531
- }
532
- }
533
-
534
- peer->current_weight--;
429
+ if (peer == NULL) {
430
+ goto failed;
535
431
}
536
432
537
- rrp->tried[n] |= m;
433
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0,
434
+ "get rr peer, current: %ui %i",
435
+ rrp->current, peer->current_weight);
538
436
}
539
437
540
438
pc->sockaddr = peer->sockaddr;
@@ -545,11 +443,6 @@ ngx_http_upstream_get_round_robin_peer(ngx_peer_connection_t *pc, void *data)
545
443
546
444
if (pc->tries == 1 && rrp->peers->next) {
547
445
pc->tries += rrp->peers->next->number;
548
-
549
- n = rrp->peers->next->number / (8 * sizeof(uintptr_t)) + 1;
550
- for (i = 0; i < n; i++) {
551
- rrp->tried[i] = 0;
552
- }
553
446
}
554
447
555
448
return NGX_OK;
@@ -595,56 +488,71 @@ ngx_http_upstream_get_round_robin_peer(ngx_peer_connection_t *pc, void *data)
595
488
}
596
489
597
490
598
-static ngx_uint_t
599
-ngx_http_upstream_get_peer(ngx_http_upstream_rr_peers_t *peers)
491
+static ngx_http_upstream_rr_peer_t *
492
+ngx_http_upstream_get_peer(ngx_http_upstream_rr_peer_data_t *rrp)
600
493
{
601
- ngx_uint_t i, n, reset = 0;
602
- ngx_http_upstream_rr_peer_t *peer;
494
+ time_t now;
495
+ uintptr_t m;
496
+ ngx_int_t total;
497
+ ngx_uint_t i, n;
498
+ ngx_http_upstream_rr_peer_t *peer, *best;
603
499
604
- peer = &peers->peer[0];
500
+ now = ngx_time();
605
501
606
- for ( ;; ) {
502
+ best = NULL;
503
+ total = 0;
607
504
608
- for (i = 0; i < peers->number; i++) {
505
+ for (i = 0; i < rrp->peers->number; i++) {
609
506
610
- if (peer[i].current_weight <= 0) {
611
- continue;
612
- }
507
+ n = i / (8 * sizeof(uintptr_t));
508
+ m = (uintptr_t) 1 << i % (8 * sizeof(uintptr_t));
613
509
614
- n = i;
615
-
616
- while (i < peers->number - 1) {
617
-
618
- i++;
510
+ if (rrp->tried[n] & m) {
511
+ continue;
512
+ }
619
513
620
- if (peer[i].current_weight <= 0) {
621
- continue;
622
- }
514
+ peer = &rrp->peers->peer[i];
623
515
624
- if (peer[n].current_weight * 1000 / peer[i].current_weight
625
- > peer[n].weight * 1000 / peer[i].weight)
626
- {
627
- return n;
628
- }
516
+ if (peer->down) {
517
+ continue;
518
+ }
629
519
630
- n = i;
631
- }
520
+ if (peer->max_fails
521
+ && peer->fails >= peer->max_fails
522
+ && now - peer->checked <= peer->fail_timeout)
523
+ {
524
+ continue;
525
+ }
632
526
633
- if (peer[i].current_weight > 0) {
634
- n = i;
635
- }
527
+ peer->current_weight += peer->effective_weight;
528
+ total += peer->effective_weight;
636
529
637
- return n;
530
+ if (peer->effective_weight < peer->weight) {
531
+ peer->effective_weight++;
638
532
}
639
533
640
- if (reset++) {
641
- return 0;
534
+ if (best == NULL || peer->current_weight > best->current_weight) {
535
+ best = peer;
642
536
}
537
+ }
643
538
644
- for (i = 0; i < peers->number; i++) {
645
- peer[i].current_weight = peer[i].weight;
646
- }
539
+ if (best == NULL) {
540
+ return NULL;
647
541
}
542
+
543
+ i = best - &rrp->peers->peer[0];
544
+
545
+ rrp->current = i;
546
+
547
+ n = i / (8 * sizeof(uintptr_t));
548
+ m = (uintptr_t) 1 << i % (8 * sizeof(uintptr_t));
549
+
550
+ rrp->tried[n] |= m;
551
+
552
+ best->current_weight -= total;
553
+ best->checked = now;
554
+
555
+ return best;
648
556
}
649
557
650
558
@@ -683,15 +591,15 @@ ngx_http_upstream_free_round_robin_peer(ngx_peer_connection_t *pc, void *data,
683
591
peer->checked = now;
684
592
685
593
if (peer->max_fails) {
686
- peer->current_weight -= peer->weight / peer->max_fails;
594
+ peer->effective_weight -= peer->weight / peer->max_fails;
687
595
}
688
596
689
597
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0,
690
598
"free rr peer failed: %ui %i",
691
- rrp->current, peer->current_weight);
599
+ rrp->current, peer->effective_weight);
692
600
693
- if (peer->current_weight < 0) {
694
- peer->current_weight = 0;
601
+ if (peer->effective_weight < 0) {
602
+ peer->effective_weight = 0;
695
603
}
696
604
697
605
/* ngx_unlock_mutex(rrp->peers->mutex); */
@@ -705,12 +613,6 @@ ngx_http_upstream_free_round_robin_peer(ngx_peer_connection_t *pc, void *data,
705
613
}
706
614
}
707
615
708
- rrp->current++;
709
-
710
- if (rrp->current >= rrp->peers->number) {
711
- rrp->current = 0;
712
- }
713
-
714
616
if (pc->tries) {
715
617
pc->tries--;
716
618
}