From 1a0a3b549cc1946821c145dde54fc4266353f43e Mon Sep 17 00:00:00 2001 From: Jim Jagielski Date: Mon, 18 Aug 2008 15:59:48 +0000 Subject: [PATCH] Add in bybusyness LB method, via Joel Gluth in https://issues.apache.org/bugzilla/show_bug.cgi?id=45501 NOTE: Name changed and added in to ease enhancement/bugfixes git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@686805 13f79535-47bb-0310-9956-ffa450edef68 --- docs/manual/mod/mod_proxy.xml | 5 +- docs/manual/mod/mod_proxy_balancer.xml | 29 +++++-- modules/proxy/mod_proxy_balancer.c | 102 +++++++++++++++++++++++++ 3 files changed, 129 insertions(+), 7 deletions(-) diff --git a/docs/manual/mod/mod_proxy.xml b/docs/manual/mod/mod_proxy.xml index f1ec76d713..a87567b715 100644 --- a/docs/manual/mod/mod_proxy.xml +++ b/docs/manual/mod/mod_proxy.xml @@ -818,8 +818,9 @@ expressions byrequests Balancer load-balance method. Select the load-balancing scheduler method to use. Either byrequests, to perform weighted - request counting or bytraffic, to perform weighted - traffic byte count balancing. Default is byrequests. + request counting, bytraffic, to perform weighted + traffic byte count balancing, or bybusyness, to perform + pending request balancing. Default is byrequests. maxattempts 1 diff --git a/docs/manual/mod/mod_proxy_balancer.xml b/docs/manual/mod/mod_proxy_balancer.xml index 925dbd2409..1097f71d81 100644 --- a/docs/manual/mod/mod_proxy_balancer.xml +++ b/docs/manual/mod/mod_proxy_balancer.xml @@ -50,11 +50,11 @@
Load balancer scheduler algorithm -

At present, there are 2 load balancer scheduler algorithms available - for use: Request Counting and Weighted Traffic Counting. These are controlled - via the lbmethod value of the Balancer definition. See - the ProxyPass directive for - more information.

+

At present, there are 3 load balancer scheduler algorithms available + for use: Request Counting, Weighted Traffic Counting and Pending Request + Counting. These are controlled via the lbmethod value of + the Balancer definition. See the ProxyPass + directive for more information.

@@ -287,6 +287,25 @@ candidate lbstatus -= total factor +
+ + Pending Request Counting Algorithm + +

Enabled via lbmethod=bybusyness, this scheduler keeps + track of how many requests each worker is assigned at present. A new + request is automatically assigned to the worker with the lowest + number of active requests. This is useful in the case of workers + that queue incoming requests independently of Apache, to ensure that + queue length stays even and a request is always given to the worker + most likely to service it fastest.

+ +

In the case of multiple least-busy workers, the statistics (and + weightings) used by the Request Counting method are used to break the + tie. Over time, the distribution of work will come to resemble that + characteristic of byrequests.

+ +
+
Exported Environment Variables

At present there are 6 environment variables exported:

diff --git a/modules/proxy/mod_proxy_balancer.c b/modules/proxy/mod_proxy_balancer.c index 7b65db9931..a03650764d 100644 --- a/modules/proxy/mod_proxy_balancer.c +++ b/modules/proxy/mod_proxy_balancer.c @@ -367,7 +367,9 @@ static proxy_worker *find_best_worker(proxy_balancer *balancer, } #endif } + return candidate; + } static int rewrite_url(request_rec *r, proxy_worker *worker, @@ -538,6 +540,8 @@ static int proxy_balancer_pre_request(proxy_worker **worker, *worker = runtime; } + (*worker)->s->busy++; + /* Add balancer/worker info to env. */ apr_table_setn(r->subprocess_env, "BALANCER_NAME", (*balancer)->name); @@ -598,7 +602,11 @@ static int proxy_balancer_post_request(proxy_worker *worker, #endif + if (worker && worker->s->busy) + worker->s->busy--; + return OK; + } static void recalc_factors(proxy_balancer *balancer) @@ -1111,6 +1119,91 @@ static proxy_worker *find_best_bytraffic(proxy_balancer *balancer, return mycandidate; } +static proxy_worker *find_best_bybusyness(proxy_balancer *balancer, + request_rec *r) +{ + + int i; + proxy_worker *worker; + proxy_worker *mycandidate = NULL; + int cur_lbset = 0; + int max_lbset = 0; + int checking_standby; + int checked_standby; + + int total_factor = 0; + + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, + "proxy: Entering bybusyness for BALANCER (%s)", + balancer->name); + + /* First try to see if we have available candidate */ + do { + + checking_standby = checked_standby = 0; + while (!mycandidate && !checked_standby) { + + worker = (proxy_worker *)balancer->workers->elts; + for (i = 0; i < balancer->workers->nelts; i++, worker++) { + if (!checking_standby) { /* first time through */ + if (worker->s->lbset > max_lbset) + max_lbset = worker->s->lbset; + } + + if (worker->s->lbset > cur_lbset) + continue; + + if ( (checking_standby ? !PROXY_WORKER_IS_STANDBY(worker) : PROXY_WORKER_IS_STANDBY(worker)) ) + continue; + + /* If the worker is in error state run + * retry on that worker. It will be marked as + * operational if the retry timeout is elapsed. + * The worker might still be unusable, but we try + * anyway. + */ + if (!PROXY_WORKER_IS_USABLE(worker)) + ap_proxy_retry_worker("BALANCER", worker, r->server); + + /* Take into calculation only the workers that are + * not in error state or not disabled. + */ + if (PROXY_WORKER_IS_USABLE(worker)) { + + worker->s->lbstatus += worker->s->lbfactor; + total_factor += worker->s->lbfactor; + + if (!mycandidate + || worker->s->busy < mycandidate->s->busy + || (worker->s->busy == mycandidate->s->busy && worker->s->lbstatus > mycandidate->s->lbstatus)) + mycandidate = worker; + + } + + } + + checked_standby = checking_standby++; + + } + + cur_lbset++; + + } while (cur_lbset <= max_lbset && !mycandidate); + + if (mycandidate) { + + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, + "proxy: selected worker \"%s\" by busy factor %i (request lbstatus %i)", + mycandidate->name, mycandidate->s->busy, mycandidate->s->lbstatus); + + mycandidate->s->lbstatus -= total_factor; + + } + + return mycandidate; + +} + /* * How to add additional lbmethods: * 1. Create func which determines "best" candidate worker @@ -1131,6 +1224,14 @@ static const proxy_balancer_method bytraffic = NULL }; +static const proxy_balancer_method bybusyness = +{ + "bybusyness", + &find_best_bybusyness, + NULL +}; + + static void ap_proxy_balancer_register_hook(apr_pool_t *p) { /* Only the mpm_winnt has child init hook handler. @@ -1147,6 +1248,7 @@ static void ap_proxy_balancer_register_hook(apr_pool_t *p) proxy_hook_canon_handler(proxy_balancer_canon, NULL, NULL, APR_HOOK_FIRST); ap_register_provider(p, PROXY_LBMETHOD, "bytraffic", "0", &bytraffic); ap_register_provider(p, PROXY_LBMETHOD, "byrequests", "0", &byrequests); + ap_register_provider(p, PROXY_LBMETHOD, "bybusyness", "0", &bybusyness); } module AP_MODULE_DECLARE_DATA proxy_balancer_module = { -- 2.40.0