mirror of
https://github.com/nginx/nginx.git
synced 2025-06-28 10:10:39 +08:00
fair upstream weight balancer
This commit is contained in:
parent
07c1f2f9aa
commit
d12a5718d8
@ -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); */
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user