Feature #594
closedFix and addon for mod_proxy balance round-robin
Description
We were looking for a small and fast thing to perform basic load-balancing functionality. We have at least 5 web servers that get hit with traffic badly (national RTV station) so we already transfered all static content onto one lighttpd server (still working on moving all dynamic contnet from Apache to FCGI). The round-robin proxy method seemd ideal, but as many pointed out, it just didn't work (I worked with 1.4.10 from Debian tree and went later on to 1.4.11 and svn merge-1.4.x).
I changed the RR code so it balances, but later added another parameter to servers array. weight gives more weight to a server.
Example:
proxy.balance = "round-robin" proxy.server = ( "" => ( ( "host" => "10.1.3.145", "port" => 80 ), ( "host" => "10.1.3.146", "port" => 80, "weight" => 7 ), ( "host" => "10.1.3.147", "port" => 80 ), ( "host" => "10.1.3.148", "port" => 80, "weight" => 3 ) ) )
I'm appending the patch below if anyone want's to play with it. I hope similar functionality makes it into the main branch some day soon.
Thank you for creating lighttpd. It kick's the hell out of web serving. q:)
lighttpd-1.4.11-mod_proxy.diff
Index: src/array.h =================================================================== --- src/array.h (revision 1043) +++ src/array.h (working copy) @@ -129,6 +129,8 @@ int usage; /* fair-balancing needs the no. of connections active on this host */ int last_used_ndx; /* round robin */ + int weight; /* round robin weight */ + int weight_left; /* round robin weight */ } data_fastcgi; data_fastcgi *data_fastcgi_init(void); Index: src/mod_proxy.c =================================================================== --- src/mod_proxy.c (revision 1043) +++ src/mod_proxy.c (working copy) @@ -276,6 +276,7 @@ config_values_t pcv[] = { { "host", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */ { "port", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 1 */ + { "weight", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 2 */ { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET } }; @@ -291,11 +292,14 @@ df = data_proxy_init(); df->port = 80; + df->last_used_ndx = -1; + df->weight = 1; buffer_copy_string_buffer(df->key, da_host->key); pcv[0].destination = df->host; pcv[1].destination = &(df->port); + pcv[2].destination = &(df->weight); if (0 != config_insert_values_internal(srv, da_host->value, pcv)) { return HANDLER_ERROR; @@ -312,6 +316,8 @@ return HANDLER_ERROR; } + df->weight_left = df->weight; + /* if extension already exists, take it */ if (NULL == (dfa = (data_array *)array_get_element(s->extensions, da_ext->key->ptr))) { @@ -1184,6 +1190,7 @@ for (k = 0, ndx = -1, max_usage = INT_MAX; k < extension->value->used; k++) { data_proxy *host = (data_proxy *)extension->value->data[k]; + data_proxy *host0 = (data_proxy *)extension->value->data[0]; if (host->is_disabled) continue; @@ -1192,18 +1199,37 @@ max_usage = k; } - /* get next ndx */ - if ((int)k > host->last_used_ndx) { + /* first usable ndx w/ weight left */ + if (host->weight_left > 0) { + max_usage = k; + } + /* get next ndx that has some weight left */ + if ((host0->last_used_ndx < (int)k) && (host->weight_left > 0)) { ndx = k; - host->last_used_ndx = k; - + host0->last_used_ndx = k; + host->weight_left--; + break; } } - /* didn't found a higher id, wrap to the start */ - if (ndx != -1 && max_usage != INT_MAX) { + /* No host found. Circle back or restore default weight info */ + if (ndx == -1 && max_usage != INT_MAX) { + data_proxy *host0 = (data_proxy *)extension->value->data[0]; + data_proxy *host = (data_proxy *)extension->value->data[max_usage]; + ndx = max_usage; + host0->last_used_ndx = ndx; + + if (host->weight_left == 0) { + for (k = 0; k < extension->value->used; k++) { + data_proxy *host = (data_proxy *)extension->value->data[k]; + + host->weight_left = host->weight; + } + } + + host->weight_left--; } break;
-- Zobo
Files
Updated by stbuehler over 16 years ago
- Status changed from New to Fixed
- Resolution set to wontfix
I think it is just easier to specify a backend multiple times to increase its weight; the patch doesn't apply anymore.
Also available in: Atom