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
}
0 commit comments