fair upstream weight balancer

This commit is contained in:
Igor Sysoev 2007-07-28 16:04:01 +00:00
parent 07c1f2f9aa
commit d12a5718d8
2 changed files with 80 additions and 36 deletions

View File

@ -9,6 +9,10 @@
#include <ngx_http.h> #include <ngx_http.h>
static ngx_uint_t
ngx_http_upstream_get_peer(ngx_http_upstream_rr_peers_t *peers);
ngx_int_t ngx_int_t
ngx_http_upstream_init_round_robin(ngx_conf_t *cf, ngx_http_upstream_init_round_robin(ngx_conf_t *cf,
ngx_http_upstream_srv_conf_t *us) ngx_http_upstream_srv_conf_t *us)
@ -215,7 +219,12 @@ ngx_http_upstream_get_round_robin_peer(ngx_peer_connection_t *pc, void *data)
/* it's a first try - get a current peer */ /* it's a first try - get a current peer */
for ( ;; ) { for ( ;; ) {
rrp->current = rrp->peers->current; rrp->current = ngx_http_upstream_get_peer(rrp->peers);
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0,
"get rr peer, current: %ui %i",
rrp->current,
rrp->peers->peer[rrp->current].current_weight);
n = rrp->current / (8 * sizeof(uintptr_t)); n = rrp->current / (8 * sizeof(uintptr_t));
m = (uintptr_t) 1 << rrp->current % (8 * sizeof(uintptr_t)); m = (uintptr_t) 1 << rrp->current % (8 * sizeof(uintptr_t));
@ -236,6 +245,8 @@ ngx_http_upstream_get_round_robin_peer(ngx_peer_connection_t *pc, void *data)
break; break;
} }
peer->current_weight = 0;
} else { } else {
rrp->tried[n] |= m; rrp->tried[n] |= m;
} }
@ -243,12 +254,6 @@ ngx_http_upstream_get_round_robin_peer(ngx_peer_connection_t *pc, void *data)
pc->tries--; pc->tries--;
} }
rrp->peers->current++;
if (rrp->peers->current >= rrp->peers->number) {
rrp->peers->current = 0;
}
if (pc->tries) { if (pc->tries) {
continue; continue;
} }
@ -258,16 +263,6 @@ ngx_http_upstream_get_round_robin_peer(ngx_peer_connection_t *pc, void *data)
peer->current_weight--; peer->current_weight--;
if (peer->current_weight == 0) {
peer->current_weight = peer->weight;
rrp->peers->current++;
if (rrp->peers->current >= rrp->peers->number) {
rrp->peers->current = 0;
}
}
} else { } else {
for ( ;; ) { for ( ;; ) {
n = rrp->current / (8 * sizeof(uintptr_t)); n = rrp->current / (8 * sizeof(uintptr_t));
@ -290,6 +285,8 @@ ngx_http_upstream_get_round_robin_peer(ngx_peer_connection_t *pc, void *data)
break; break;
} }
peer->current_weight = 0;
} else { } else {
rrp->tried[n] |= m; rrp->tried[n] |= m;
} }
@ -311,18 +308,6 @@ ngx_http_upstream_get_round_robin_peer(ngx_peer_connection_t *pc, void *data)
} }
peer->current_weight--; peer->current_weight--;
if (peer->current_weight == 0) {
peer->current_weight = peer->weight;
if (rrp->current == rrp->peers->current) {
rrp->peers->current++;
if (rrp->peers->current >= rrp->peers->number) {
rrp->peers->current = 0;
}
}
}
} }
rrp->tried[n] |= m; rrp->tried[n] |= m;
@ -352,6 +337,61 @@ failed:
} }
static ngx_uint_t
ngx_http_upstream_get_peer(ngx_http_upstream_rr_peers_t *peers)
{
ngx_uint_t i, n;
ngx_http_upstream_rr_peer_t *peer;
peer = &peers->peer[0];
for ( ;; ) {
for (i = 0; i < peers->number; i++) {
if (peer[i].current_weight <= 0) {
continue;
}
n = i;
while (i < peers->number - 1) {
i++;
if (peer[i].current_weight <= 0) {
continue;
}
if (peer[n].current_weight * 1000 / peer[i].current_weight
>= peer[n].weight * 1000 / peer[i].weight)
{
return n;
}
n = i;
}
if (peer[i].current_weight > 0) {
n = i;
}
return n;
}
for (i = 0; i < peers->number; i++) {
if (peer[i].fails == 0) {
peer[i].current_weight += peer[i].weight;
} else {
/* 1 allows to go to quick recovery when all peers failed */
peer[i].current_weight = 1;
}
}
}
}
void void
ngx_http_upstream_free_round_robin_peer(ngx_peer_connection_t *pc, void *data, ngx_http_upstream_free_round_robin_peer(ngx_peer_connection_t *pc, void *data,
ngx_uint_t state) ngx_uint_t state)
@ -385,8 +425,14 @@ ngx_http_upstream_free_round_robin_peer(ngx_peer_connection_t *pc, void *data,
peer->fails++; peer->fails++;
peer->accessed = now; peer->accessed = now;
if (peer->current_weight > 1) { peer->current_weight -= peer->weight / peer->max_fails;
peer->current_weight /= 2;
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0,
"free rr peer failed: %ui %i",
rrp->current, peer->current_weight);
if (peer->current_weight < 0) {
peer->current_weight = 0;
} }
/* ngx_unlock_mutex(rrp->peers->mutex); */ /* ngx_unlock_mutex(rrp->peers->mutex); */

View File

@ -18,8 +18,8 @@ typedef struct {
socklen_t socklen; socklen_t socklen;
ngx_str_t name; ngx_str_t name;
ngx_uint_t current_weight; ngx_int_t current_weight;
ngx_uint_t weight; ngx_int_t weight;
ngx_uint_t fails; ngx_uint_t fails;
time_t accessed; time_t accessed;
@ -29,15 +29,13 @@ typedef struct {
ngx_uint_t down; /* unsigned down:1; */ ngx_uint_t down; /* unsigned down:1; */
#if (NGX_SSL) #if (NGX_HTTP_SSL)
ngx_ssl_session_t *ssl_session; /* local to a process */ ngx_ssl_session_t *ssl_session; /* local to a process */
#endif #endif
} ngx_http_upstream_rr_peer_t; } ngx_http_upstream_rr_peer_t;
typedef struct { typedef struct {
ngx_uint_t current;
ngx_uint_t number; ngx_uint_t number;
ngx_uint_t last_cached; ngx_uint_t last_cached;