fair upstream weight balancer
This commit is contained in:
parent
4d12a376e8
commit
a6d25b840f
2 changed files with 80 additions and 36 deletions
|
@ -9,6 +9,10 @@
|
|||
#include <ngx_http.h>
|
||||
|
||||
|
||||
static ngx_uint_t
|
||||
ngx_http_upstream_get_peer(ngx_http_upstream_rr_peers_t *peers);
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_http_upstream_init_round_robin(ngx_conf_t *cf,
|
||||
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 */
|
||||
|
||||
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));
|
||||
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;
|
||||
}
|
||||
|
||||
peer->current_weight = 0;
|
||||
|
||||
} else {
|
||||
rrp->tried[n] |= m;
|
||||
}
|
||||
|
@ -243,12 +254,6 @@ ngx_http_upstream_get_round_robin_peer(ngx_peer_connection_t *pc, void *data)
|
|||
pc->tries--;
|
||||
}
|
||||
|
||||
rrp->peers->current++;
|
||||
|
||||
if (rrp->peers->current >= rrp->peers->number) {
|
||||
rrp->peers->current = 0;
|
||||
}
|
||||
|
||||
if (pc->tries) {
|
||||
continue;
|
||||
}
|
||||
|
@ -258,16 +263,6 @@ ngx_http_upstream_get_round_robin_peer(ngx_peer_connection_t *pc, void *data)
|
|||
|
||||
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 {
|
||||
for ( ;; ) {
|
||||
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;
|
||||
}
|
||||
|
||||
peer->current_weight = 0;
|
||||
|
||||
} else {
|
||||
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--;
|
||||
|
||||
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;
|
||||
|
@ -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
|
||||
ngx_http_upstream_free_round_robin_peer(ngx_peer_connection_t *pc, void *data,
|
||||
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->accessed = now;
|
||||
|
||||
if (peer->current_weight > 1) {
|
||||
peer->current_weight /= 2;
|
||||
peer->current_weight -= peer->weight / peer->max_fails;
|
||||
|
||||
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); */
|
||||
|
|
|
@ -18,8 +18,8 @@ typedef struct {
|
|||
socklen_t socklen;
|
||||
ngx_str_t name;
|
||||
|
||||
ngx_uint_t current_weight;
|
||||
ngx_uint_t weight;
|
||||
ngx_int_t current_weight;
|
||||
ngx_int_t weight;
|
||||
|
||||
ngx_uint_t fails;
|
||||
time_t accessed;
|
||||
|
@ -29,15 +29,13 @@ typedef struct {
|
|||
|
||||
ngx_uint_t down; /* unsigned down:1; */
|
||||
|
||||
#if (NGX_SSL)
|
||||
#if (NGX_HTTP_SSL)
|
||||
ngx_ssl_session_t *ssl_session; /* local to a process */
|
||||
#endif
|
||||
} ngx_http_upstream_rr_peer_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
ngx_uint_t current;
|
||||
|
||||
ngx_uint_t number;
|
||||
ngx_uint_t last_cached;
|
||||
|
||||
|
|
Loading…
Reference in a new issue