From c9f0786eddf5a5720bd33a6a4e627d74052c1f51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Mierzwa?= Date: Thu, 4 Oct 2012 10:31:47 +0200 Subject: [PATCH 1/2] with this patch lrc acts more like rr algorithm when request rate is very low. Side effect is that when one adds new node to long running cluster, then lrc will try to catch new node request count up to other nodes value, but since it will only happen during low request rate, than I don't consider it as an issue --- core/subscription.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/subscription.c b/core/subscription.c index 82cce2ae..382105cb 100644 --- a/core/subscription.c +++ b/core/subscription.c @@ -88,7 +88,7 @@ static struct uwsgi_subscribe_node *uwsgi_subscription_algo_lrc(struct uwsgi_sub if (min_rc == 0 || node->reference < min_rc) { min_rc = node->reference; choosen_node = node; - if (min_rc == 0) break; + if (min_rc == 0 && !(node->next && node->next->reference <= node->reference && node->next->requests <= node->requests)) break; } } node = node->next; From 86ea390ba8a141ccf3e55033e8d066d94d38afe0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Mierzwa?= Date: Sat, 6 Oct 2012 12:27:56 +0200 Subject: [PATCH 2/2] weighted least reference count (wlrc) load balancing algorithm --- core/subscription.c | 43 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/core/subscription.c b/core/subscription.c index 382105cb..1bb81607 100644 --- a/core/subscription.c +++ b/core/subscription.c @@ -82,13 +82,47 @@ static struct uwsgi_subscribe_node *uwsgi_subscription_algo_lrc(struct uwsgi_sub struct uwsgi_subscribe_node *choosen_node = NULL; node = current_slot->nodes; - uint64_t min_rc = 0; + uint64_t min_rc = 0; while(node) { if (!node->death_mark) { if (min_rc == 0 || node->reference < min_rc) { min_rc = node->reference; choosen_node = node; - if (min_rc == 0 && !(node->next && node->next->reference <= node->reference && node->next->requests <= node->requests)) break; + if (min_rc == 0 && !(node->next && node->next->reference <= node->reference && node->next->requests <= node->requests)) + break; + } + } + node = node->next; + } + + if (choosen_node) { + choosen_node->reference++; + } + + return choosen_node; +} + +// weighted least reference count +static struct uwsgi_subscribe_node *uwsgi_subscription_algo_wlrc(struct uwsgi_subscribe_slot *current_slot, struct uwsgi_subscribe_node *node) { + // if node is NULL we are in the second step (in wlrc mode we do not use the first step) + if (node) return NULL; + + struct uwsgi_subscribe_node *choosen_node = NULL; + node = current_slot->nodes; + double min_rc = 0; + while(node) { + if (!node->death_mark) { + // node->weight is always >= 1, we can safely use it as divider + double ref = (double) node->reference / (double) node->weight; + double next_node_ref = 0; + if (node->next) + next_node_ref = (double) node->next->reference / (double) node->next->weight; + + if (min_rc == 0 || ref < min_rc) { + min_rc = ref; + choosen_node = node; + if (min_rc == 0 && !(node->next && next_node_ref <= ref && node->next->requests <= node->requests)) + break; } } node = node->next; @@ -154,6 +188,11 @@ void uwsgi_subscription_set_algo(char *algo) { return; } + if (!strcmp(algo,"wlrc")) { + uwsgi.subscription_algo = uwsgi_subscription_algo_wlrc; + return; + } + wrr: uwsgi.subscription_algo = uwsgi_subscription_algo_wrr; }