From a61e6b29860cd4a584327962b04307b2f9ca5388 Mon Sep 17 00:00:00 2001 From: Augists Date: Mon, 11 Aug 2025 19:34:09 +0800 Subject: [PATCH 1/2] swrr: Introduce Random Smooth Weighted Round Robin to Solve Herd Effect in Cluster Deployment --- src/http/ngx_http_upstream_round_robin.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/http/ngx_http_upstream_round_robin.c b/src/http/ngx_http_upstream_round_robin.c index 4637318d1..ae76933e6 100644 --- a/src/http/ngx_http_upstream_round_robin.c +++ b/src/http/ngx_http_upstream_round_robin.c @@ -203,7 +203,7 @@ ngx_http_upstream_init_round_robin(ngx_conf_t *cf, peer[n].socklen = server[i].addrs[j].socklen; peer[n].name = server[i].addrs[j].name; peer[n].weight = server[i].weight; - peer[n].effective_weight = server[i].weight; + peer[n].effective_weight = 1; /* Initialize to 1 instead of server[i].weight for randomness */ peer[n].current_weight = 0; peer[n].max_conns = server[i].max_conns; peer[n].max_fails = server[i].max_fails; @@ -329,7 +329,7 @@ ngx_http_upstream_init_round_robin(ngx_conf_t *cf, peer[n].socklen = server[i].addrs[j].socklen; peer[n].name = server[i].addrs[j].name; peer[n].weight = server[i].weight; - peer[n].effective_weight = server[i].weight; + peer[n].effective_weight = 1; /* Initialize to 1 instead of server[i].weight for randomness */ peer[n].current_weight = 0; peer[n].max_conns = server[i].max_conns; peer[n].max_fails = server[i].max_fails; @@ -751,7 +751,15 @@ ngx_http_upstream_get_peer(ngx_http_upstream_rr_peer_data_t *rrp) peer->effective_weight++; } - if (best == NULL || peer->current_weight > best->current_weight) { + /* + * Introduce randomness to solve the herd effect in cluster deployment + * When two peers have equal current weights, use random number to decide which one to choose + */ + if (best == NULL + || peer->current_weight > best->current_weight + || (peer->current_weight == best->current_weight + && ngx_random() % 2)) + { best = peer; p = i; } From 74e921a1f64dfcffdd851b6e5b8f9ea15a138bae Mon Sep 17 00:00:00 2001 From: Augists Date: Tue, 19 Aug 2025 20:11:08 +0800 Subject: [PATCH 2/2] swrr: Add randomness to peer selection --- src/http/ngx_http_upstream_round_robin.c | 6 ++++-- src/stream/ngx_stream_upstream_round_robin.c | 22 +++++++++++++++----- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/http/ngx_http_upstream_round_robin.c b/src/http/ngx_http_upstream_round_robin.c index ae76933e6..36d151d90 100644 --- a/src/http/ngx_http_upstream_round_robin.c +++ b/src/http/ngx_http_upstream_round_robin.c @@ -203,7 +203,8 @@ ngx_http_upstream_init_round_robin(ngx_conf_t *cf, peer[n].socklen = server[i].addrs[j].socklen; peer[n].name = server[i].addrs[j].name; peer[n].weight = server[i].weight; - peer[n].effective_weight = 1; /* Initialize to 1 instead of server[i].weight for randomness */ + /* Initialize to 1 instead of server[i].weight for randomness */ + peer[n].effective_weight = 1; peer[n].current_weight = 0; peer[n].max_conns = server[i].max_conns; peer[n].max_fails = server[i].max_fails; @@ -329,7 +330,8 @@ ngx_http_upstream_init_round_robin(ngx_conf_t *cf, peer[n].socklen = server[i].addrs[j].socklen; peer[n].name = server[i].addrs[j].name; peer[n].weight = server[i].weight; - peer[n].effective_weight = 1; /* Initialize to 1 instead of server[i].weight for randomness */ + /* Initialize to 1 instead of server[i].weight for randomness */ + peer[n].effective_weight = 1; peer[n].current_weight = 0; peer[n].max_conns = server[i].max_conns; peer[n].max_fails = server[i].max_fails; diff --git a/src/stream/ngx_stream_upstream_round_robin.c b/src/stream/ngx_stream_upstream_round_robin.c index dd80322c8..1602f122a 100644 --- a/src/stream/ngx_stream_upstream_round_robin.c +++ b/src/stream/ngx_stream_upstream_round_robin.c @@ -189,7 +189,8 @@ ngx_stream_upstream_init_round_robin(ngx_conf_t *cf, peer[n].socklen = server[i].addrs[0].socklen; peer[n].name = server[i].addrs[0].name; peer[n].weight = server[i].weight; - peer[n].effective_weight = server[i].weight; + /* Initialize to 1 instead of server[i].weight for randomness */ + peer[n].effective_weight = 1; peer[n].current_weight = 0; peer[n].max_conns = server[i].max_conns; peer[n].max_fails = server[i].max_fails; @@ -209,7 +210,8 @@ ngx_stream_upstream_init_round_robin(ngx_conf_t *cf, peer[n].socklen = server[i].addrs[j].socklen; peer[n].name = server[i].addrs[j].name; peer[n].weight = server[i].weight; - peer[n].effective_weight = server[i].weight; + /* Initialize to 1 instead of server[i].weight for randomness */ + peer[n].effective_weight = 1; peer[n].current_weight = 0; peer[n].max_conns = server[i].max_conns; peer[n].max_fails = server[i].max_fails; @@ -314,7 +316,8 @@ ngx_stream_upstream_init_round_robin(ngx_conf_t *cf, peer[n].socklen = server[i].addrs[0].socklen; peer[n].name = server[i].addrs[0].name; peer[n].weight = server[i].weight; - peer[n].effective_weight = server[i].weight; + /* Initialize to 1 instead of server[i].weight for randomness */ + peer[n].effective_weight = 1; peer[n].current_weight = 0; peer[n].max_conns = server[i].max_conns; peer[n].max_fails = server[i].max_fails; @@ -334,7 +337,8 @@ ngx_stream_upstream_init_round_robin(ngx_conf_t *cf, peer[n].socklen = server[i].addrs[j].socklen; peer[n].name = server[i].addrs[j].name; peer[n].weight = server[i].weight; - peer[n].effective_weight = server[i].weight; + /* Initialize to 1 instead of server[i].weight for randomness */ + peer[n].effective_weight = 1; peer[n].current_weight = 0; peer[n].max_conns = server[i].max_conns; peer[n].max_fails = server[i].max_fails; @@ -760,7 +764,15 @@ ngx_stream_upstream_get_peer(ngx_stream_upstream_rr_peer_data_t *rrp) peer->effective_weight++; } - if (best == NULL || peer->current_weight > best->current_weight) { + /* + * Introduce randomness to solve the herd effect in cluster deployment + * When two peers have equal current weights, use random number to decide which one to choose + */ + if (best == NULL + || peer->current_weight > best->current_weight + || (peer->current_weight == best->current_weight + && ngx_random() % 2)) + { best = peer; p = i; }