From: Jim Jagielski Date: Wed, 7 Sep 2005 12:04:15 +0000 (+0000) Subject: Restruct of lbmethod find-best algo's, bypassing hook mechanism. X-Git-Tag: 2.3.0~3022 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=da3e833d3089d3cea9ad55f29889705b8110380a;p=apache Restruct of lbmethod find-best algo's, bypassing hook mechanism. Looking into provider method, but until then... Prevent core dump when balancer not in vhosts git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@279305 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/modules/proxy/mod_proxy.c b/modules/proxy/mod_proxy.c index 1f3de0c117..9cac88778f 100644 --- a/modules/proxy/mod_proxy.c +++ b/modules/proxy/mod_proxy.c @@ -822,7 +822,7 @@ static void * create_proxy_config(apr_pool_t *p, server_rec *s) ps->badopt_set = 0; ps->pool = p; - proxy_run_load_lbmethods(ps); + ap_proxy_add_lbmethods(ps); return ps; } @@ -1925,7 +1925,6 @@ APR_HOOK_STRUCT( APR_HOOK_LINK(canon_handler) APR_HOOK_LINK(pre_request) APR_HOOK_LINK(post_request) - APR_HOOK_LINK(load_lbmethods) APR_HOOK_LINK(request_status) ) @@ -1951,10 +1950,6 @@ APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(proxy, PROXY, int, post_request, request_rec *r, proxy_server_conf *conf),(worker, balancer,r,conf),DECLINED) -APR_IMPLEMENT_EXTERNAL_HOOK_RUN_ALL(proxy, PROXY, int, load_lbmethods, - (proxy_server_conf *conf), - (conf), - OK, DECLINED) APR_IMPLEMENT_OPTIONAL_HOOK_RUN_ALL(proxy, PROXY, int, fixups, (request_rec *r), (r), OK, DECLINED) diff --git a/modules/proxy/mod_proxy.h b/modules/proxy/mod_proxy.h index fd223ad1a2..5cbaed148c 100644 --- a/modules/proxy/mod_proxy.h +++ b/modules/proxy/mod_proxy.h @@ -379,14 +379,6 @@ APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, canon_handler, (request_rec *r, APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, create_req, (request_rec *r, request_rec *pr)) APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, fixups, (request_rec *r)) -/* - * Useful hook run within the create per-server phase which - * adds the required lbmethod structs, so they exist at - * configure time - */ -APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, load_lbmethods, - (proxy_server_conf *conf)) - /** * pre request hook. * It will return the most suitable worker at the moment @@ -678,6 +670,14 @@ PROXY_DECLARE(int) ap_proxy_connection_create(const char *proxy_function, proxy_conn_rec *conn, conn_rec *c, server_rec *s); +/** + * Load in available lb methods + * @param conf server conf + * @return OK or HTTP_XXX error + */ + +PROXY_DECLARE(int) ap_proxy_add_lbmethods(proxy_server_conf *conf); + /* Scoreboard */ #if MODULE_MAGIC_NUMBER_MAJOR > 20020903 #define PROXY_HAS_SCOREBOARD 1 diff --git a/modules/proxy/mod_proxy_balancer.c b/modules/proxy/mod_proxy_balancer.c index 0d9921e96c..7bb3d1252f 100644 --- a/modules/proxy/mod_proxy_balancer.c +++ b/modules/proxy/mod_proxy_balancer.c @@ -218,156 +218,6 @@ static proxy_worker *find_session_route(proxy_balancer *balancer, return NULL; } -/* - * The idea behind the find_best_byrequests scheduler is the following: - * - * lbfactor is "how much we expect this worker to work", or "the worker's - * normalized work quota". - * - * lbstatus is "how urgent this worker has to work to fulfill its quota - * of work". - * - * We distribute each worker's work quota to the worker, and then look - * which of them needs to work most urgently (biggest lbstatus). This - * worker is then selected for work, and its lbstatus reduced by the - * total work quota we distributed to all workers. Thus the sum of all - * lbstatus does not change.(*) - * - * If some workers are disabled, the others will - * still be scheduled correctly. - * - * If a balancer is configured as follows: - * - * worker a b c d - * lbfactor 25 25 25 25 - * - * And b gets disabled, the following schedule is produced: - * - * a c d a c d a c d ... - * - * Note that the above lbfactor setting is the *exact* same as: - * - * worker a b c d - * lbfactor 1 1 1 1 - * - * Asymmetric configurations work as one would expect. For - * example: - * - * worker a b c d - * lbfactor 1 1 1 2 - * - * would have a, b and c all handling about the same - * amount of load with d handling twice what a or b - * or c handles individually. So we could see: - * - * b a d c d a c d b d ... - * - */ - -static proxy_worker *find_best_byrequests(proxy_balancer *balancer, - request_rec *r) -{ - int i; - int total_factor = 0; - proxy_worker *worker = (proxy_worker *)balancer->workers->elts; - proxy_worker *mycandidate = NULL; - - - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, - "proxy: Entering byrequests for BALANCER (%s)", - balancer->name); - - /* First try to see if we have available candidate */ - for (i = 0; i < balancer->workers->nelts; i++) { - /* 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->lbstatus > mycandidate->s->lbstatus) - mycandidate = worker; - } - worker++; - } - - if (mycandidate) { - mycandidate->s->lbstatus -= total_factor; - mycandidate->s->elected++; - } - - return mycandidate; -} - -/* - * The idea behind the find_best_bytraffic scheduler is the following: - * - * We know the amount of traffic (bytes in and out) handled by each - * worker. We normalize that traffic by each workers' weight. So assuming - * a setup as below: - * - * worker a b c - * lbfactor 1 1 3 - * - * the scheduler will allow worker c to handle 3 times the - * traffic of a and b. If each request/response results in the - * same amount of traffic, then c would be accessed 3 times as - * often as a or b. If, for example, a handled a request that - * resulted in a large i/o bytecount, then b and c would be - * chosen more often, to even things out. - */ -static proxy_worker *find_best_bytraffic(proxy_balancer *balancer, - request_rec *r) -{ - int i; - apr_off_t mytraffic = 0; - apr_off_t curmin = 0; - proxy_worker *worker = (proxy_worker *)balancer->workers->elts; - proxy_worker *mycandidate = NULL; - - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, - "proxy: Entering bytraffic for BALANCER (%s)", - balancer->name); - - /* First try to see if we have available candidate */ - for (i = 0; i < balancer->workers->nelts; i++) { - /* 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)) { - mytraffic = (worker->s->transferred/worker->s->lbfactor) + - (worker->s->read/worker->s->lbfactor); - if (!mycandidate || mytraffic < curmin) { - mycandidate = worker; - curmin = mytraffic; - } - } - worker++; - } - - if (mycandidate) { - mycandidate->s->elected++; - } - - return mycandidate; -} - static proxy_worker *find_best_worker(proxy_balancer *balancer, request_rec *r) { @@ -888,30 +738,6 @@ static void child_init(apr_pool_t *p, server_rec *s) } -/* - * How to add additional lbmethods: - * 1. Create func which determines "best" candidate worker - * (eg: find_best_bytraffic, above) - * 2. Create proxy_balancer_method struct which - * defines the method and add it to - * available server methods using - * the proxy_hook_load_lbmethods hook - * (eg: add_lbmethods below). - */ -static int add_lbmethods(proxy_server_conf *conf) -{ - proxy_balancer_method *new; - - new = apr_array_push(conf->lbmethods); - new->name = "byrequests"; - new->finder = find_best_byrequests; - new = apr_array_push(conf->lbmethods); - new->name = "bytraffic"; - new->finder = find_best_bytraffic; - - return OK; -} - static void ap_proxy_balancer_register_hook(apr_pool_t *p) { /* Only the mpm_winnt has child init hook handler. @@ -925,7 +751,6 @@ static void ap_proxy_balancer_register_hook(apr_pool_t *p) proxy_hook_pre_request(proxy_balancer_pre_request, NULL, NULL, APR_HOOK_FIRST); proxy_hook_post_request(proxy_balancer_post_request, NULL, NULL, APR_HOOK_FIRST); proxy_hook_canon_handler(proxy_balancer_canon, NULL, NULL, APR_HOOK_FIRST); - proxy_hook_load_lbmethods(add_lbmethods, NULL, NULL, APR_HOOK_FIRST); } module AP_MODULE_DECLARE_DATA proxy_balancer_module = { diff --git a/modules/proxy/proxy_util.c b/modules/proxy/proxy_util.c index b12a955edb..15d9c61042 100644 --- a/modules/proxy/proxy_util.c +++ b/modules/proxy/proxy_util.c @@ -2069,3 +2069,176 @@ int ap_proxy_lb_workers(void) lb_workers_limit = proxy_lb_workers + PROXY_DYNAMIC_BALANCER_LIMIT; return lb_workers_limit; } + +/* + * The idea behind the find_best_byrequests scheduler is the following: + * + * lbfactor is "how much we expect this worker to work", or "the worker's + * normalized work quota". + * + * lbstatus is "how urgent this worker has to work to fulfill its quota + * of work". + * + * We distribute each worker's work quota to the worker, and then look + * which of them needs to work most urgently (biggest lbstatus). This + * worker is then selected for work, and its lbstatus reduced by the + * total work quota we distributed to all workers. Thus the sum of all + * lbstatus does not change.(*) + * + * If some workers are disabled, the others will + * still be scheduled correctly. + * + * If a balancer is configured as follows: + * + * worker a b c d + * lbfactor 25 25 25 25 + * + * And b gets disabled, the following schedule is produced: + * + * a c d a c d a c d ... + * + * Note that the above lbfactor setting is the *exact* same as: + * + * worker a b c d + * lbfactor 1 1 1 1 + * + * Asymmetric configurations work as one would expect. For + * example: + * + * worker a b c d + * lbfactor 1 1 1 2 + * + * would have a, b and c all handling about the same + * amount of load with d handling twice what a or b + * or c handles individually. So we could see: + * + * b a d c d a c d b d ... + * + */ + +static proxy_worker *find_best_byrequests(proxy_balancer *balancer, + request_rec *r) +{ + int i; + int total_factor = 0; + proxy_worker *worker = (proxy_worker *)balancer->workers->elts; + proxy_worker *mycandidate = NULL; + + + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, + "proxy: Entering byrequests for BALANCER (%s)", + balancer->name); + + /* First try to see if we have available candidate */ + for (i = 0; i < balancer->workers->nelts; i++) { + /* 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->lbstatus > mycandidate->s->lbstatus) + mycandidate = worker; + } + worker++; + } + + if (mycandidate) { + mycandidate->s->lbstatus -= total_factor; + mycandidate->s->elected++; + } + + return mycandidate; +} + +/* + * The idea behind the find_best_bytraffic scheduler is the following: + * + * We know the amount of traffic (bytes in and out) handled by each + * worker. We normalize that traffic by each workers' weight. So assuming + * a setup as below: + * + * worker a b c + * lbfactor 1 1 3 + * + * the scheduler will allow worker c to handle 3 times the + * traffic of a and b. If each request/response results in the + * same amount of traffic, then c would be accessed 3 times as + * often as a or b. If, for example, a handled a request that + * resulted in a large i/o bytecount, then b and c would be + * chosen more often, to even things out. + */ +static proxy_worker *find_best_bytraffic(proxy_balancer *balancer, + request_rec *r) +{ + int i; + apr_off_t mytraffic = 0; + apr_off_t curmin = 0; + proxy_worker *worker = (proxy_worker *)balancer->workers->elts; + proxy_worker *mycandidate = NULL; + + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, + "proxy: Entering bytraffic for BALANCER (%s)", + balancer->name); + + /* First try to see if we have available candidate */ + for (i = 0; i < balancer->workers->nelts; i++) { + /* 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)) { + mytraffic = (worker->s->transferred/worker->s->lbfactor) + + (worker->s->read/worker->s->lbfactor); + if (!mycandidate || mytraffic < curmin) { + mycandidate = worker; + curmin = mytraffic; + } + } + worker++; + } + + if (mycandidate) { + mycandidate->s->elected++; + } + + return mycandidate; +} + +/* + * How to add additional lbmethods: + * 1. Create func which determines "best" candidate worker + * (eg: find_best_bytraffic, above) + * 2. Create proxy_balancer_method struct which + * defines the method and add it to + * available server methods using + * ap_proxy_add_lbmethods. + */ +PROXY_DECLARE(int) ap_proxy_add_lbmethods(proxy_server_conf *conf) +{ + proxy_balancer_method *new; + + new = apr_array_push(conf->lbmethods); + new->name = "byrequests"; + new->finder = find_best_byrequests; + new = apr_array_push(conf->lbmethods); + new->name = "bytraffic"; + new->finder = find_best_bytraffic; + + return OK; +}