From: Jim Jagielski Date: Mon, 19 Sep 2005 12:52:19 +0000 (+0000) Subject: Backport of the following patches from trunk: X-Git-Tag: 2.1.8~46 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=69c7b5f5e472fc57b01d92b3113775b8d53101bb;p=thirdparty%2Fapache%2Fhttpd.git Backport of the following patches from trunk: r279973 r279752 r279579 r279319 r279305 ------------------------------------------------------------------------ r279973 | jorton | 2005-09-10 05:10:27 -0400 (Sat, 10 Sep 2005) | 5 lines * modules/proxy/mod_proxy_balancer.c (balancer_handler): Fix gcc warning; no functional change. * modules/proxy/mod_proxy.c (set_balancer_param): Likewise. ------------------------------------------------------------------------ r279752 | jim | 2005-09-09 08:28:02 -0400 (Fri, 09 Sep 2005) | 4 lines Proxy balancer lbmethods are now registered as providers and not via hooks. Move various find() functions back to mod_proxy_balancer where they belong :) ------------------------------------------------------------------------ r279579 | bnicholes | 2005-09-08 12:37:00 -0400 (Thu, 08 Sep 2005) | 1 line Remove proxy_hook_load_lbmethods from Netware export list ------------------------------------------------------------------------ r279319 | jim | 2005-09-07 09:14:16 -0400 (Wed, 07 Sep 2005) | 2 lines Minor nit. Methods are server-wide, so simply use the base version table. ------------------------------------------------------------------------ r279305 | jim | 2005-09-07 08:04:15 -0400 (Wed, 07 Sep 2005) | 4 lines 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/branches/2.2.x@290141 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/modules/proxy/NWGNUproxy b/modules/proxy/NWGNUproxy index 96368a2a55c..ac36e50beab 100644 --- a/modules/proxy/NWGNUproxy +++ b/modules/proxy/NWGNUproxy @@ -229,7 +229,6 @@ FILES_nlm_exports = \ proxy_hook_canon_handler \ proxy_hook_pre_request \ proxy_hook_post_request \ - proxy_hook_load_lbmethods \ ap_proxy_ssl_enable \ ap_proxy_ssl_disable \ ap_proxy_conn_is_https \ diff --git a/modules/proxy/ajp.h b/modules/proxy/ajp.h index e162fe97dce..8a92fa5bda5 100644 --- a/modules/proxy/ajp.h +++ b/modules/proxy/ajp.h @@ -14,6 +14,15 @@ * limitations under the License. */ +/** + * @file ajp.h + * @brief Apache Jserv Protocol + * + * @defgroup AJP_defines AJP definitions + * @ingroup MOD_PROXY + * @{ + */ + #ifndef AJP_H #define AJP_H @@ -125,10 +134,6 @@ struct ajp_msg int server_side; }; -/** - * @defgroup AJP_defines AJP definitions - * @{ - */ /** * Signature for the messages sent from Apache to tomcat */ @@ -161,6 +166,7 @@ struct ajp_msg /** * @defgroup AJP_api AJP API functions + * @ingroup MOD_PROXY * @{ */ /** diff --git a/modules/proxy/ajp_header.h b/modules/proxy/ajp_header.h index 35ac2e50f51..48d11ba31da 100644 --- a/modules/proxy/ajp_header.h +++ b/modules/proxy/ajp_header.h @@ -13,6 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +/** + * @file ajp_header.h + * @brief AJP defines + * + * @addtogroup AJP_defines + * @{ + */ + #ifndef AJP_HEADER_H #define AJP_HEADER_H @@ -163,3 +172,4 @@ #define SC_RES_HEADERS_NUM 11 #endif /* AJP_HEADER_H */ +/** @} */ diff --git a/modules/proxy/mod_proxy.c b/modules/proxy/mod_proxy.c index 1f3de0c117a..f49493a25ee 100644 --- a/modules/proxy/mod_proxy.c +++ b/modules/proxy/mod_proxy.c @@ -273,15 +273,11 @@ static const char *set_balancer_param(proxy_server_conf *conf, balancer->max_attempts_set = 1; } else if (!strcasecmp(key, "lbmethod")) { - struct proxy_balancer_method *ent = - (struct proxy_balancer_method *) conf->lbmethods->elts; - int i; - for (i = 0; i < conf->lbmethods->nelts; i++) { - if (!strcasecmp(val, ent->name)) { - balancer->lbmethod = ent; - return NULL; - } - ent++; + proxy_balancer_method *provider; + provider = ap_lookup_provider(PROXY_LBMETHOD, val, "0"); + if (provider) { + balancer->lbmethod = provider; + return NULL; } return "unknown lbmethod"; } @@ -798,7 +794,6 @@ static void * create_proxy_config(apr_pool_t *p, server_rec *s) ps->allowed_connect_ports = apr_array_make(p, 10, sizeof(int)); ps->workers = apr_array_make(p, 10, sizeof(proxy_worker)); ps->balancers = apr_array_make(p, 10, sizeof(proxy_balancer)); - ps->lbmethods = apr_array_make(p, 10, sizeof(proxy_balancer_method)); ps->forward = NULL; ps->reverse = NULL; ps->domain = NULL; @@ -821,9 +816,7 @@ static void * create_proxy_config(apr_pool_t *p, server_rec *s) ps->badopt = bad_error; ps->badopt_set = 0; ps->pool = p; - - proxy_run_load_lbmethods(ps); - + return ps; } @@ -841,7 +834,6 @@ static void * merge_proxy_config(apr_pool_t *p, void *basev, void *overridesv) ps->allowed_connect_ports = apr_array_append(p, base->allowed_connect_ports, overrides->allowed_connect_ports); ps->workers = apr_array_append(p, base->workers, overrides->workers); ps->balancers = apr_array_append(p, base->balancers, overrides->balancers); - ps->lbmethods = apr_array_append(p, base->lbmethods, overrides->lbmethods); ps->forward = overrides->forward ? overrides->forward : base->forward; ps->reverse = overrides->reverse ? overrides->reverse : base->reverse; @@ -1522,7 +1514,7 @@ static const char * err = set_balancer_param(conf, cmd->pool, balancer, word, val); if (err) - return apr_pstrcat(cmd->temp_pool, "ProxySet ", err, " ", word, " ", name, NULL); + return apr_pstrcat(cmd->temp_pool, "ProxySet: ", err, " ", word, "=", val, "; ", name, NULL); } return NULL; @@ -1925,7 +1917,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 +1942,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 43b35266176..63ed1afe2cf 100644 --- a/modules/proxy/mod_proxy.h +++ b/modules/proxy/mod_proxy.h @@ -17,8 +17,13 @@ #ifndef MOD_PROXY_H #define MOD_PROXY_H -/* - * Main include file for the Apache proxy +/** + * @file mod_proxy.h + * @brief Proxy Extension Module for Apache + * + * @defgroup MOD_PROXY mod_proxy + * @ingroup APACHE_MODS + * @{ */ /* @@ -68,6 +73,7 @@ #include "http_connection.h" #include "util_filter.h" #include "util_ebcdic.h" +#include "ap_provider.h" #if APR_HAVE_NETINET_IN_H #include @@ -180,7 +186,6 @@ typedef struct { } proxy_status; /* Status display options */ char proxy_status_set; apr_pool_t *pool; /* Pool used for allocating this struct */ - apr_array_header_t *lbmethods; } proxy_server_conf; @@ -374,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 @@ -680,6 +677,8 @@ PROXY_DECLARE(int) ap_proxy_connection_create(const char *proxy_function, #define PROXY_HAS_SCOREBOARD 0 #endif +#define PROXY_LBMETHOD "proxylbmethod" + /* The number of dynamic workers that can be added when reconfiguring. * If this limit is reached you must stop and restart the server. */ @@ -696,3 +695,4 @@ extern module PROXY_DECLARE_DATA proxy_module; extern int PROXY_DECLARE_DATA proxy_lb_workers; #endif /*MOD_PROXY_H*/ +/** @} */ diff --git a/modules/proxy/mod_proxy_balancer.c b/modules/proxy/mod_proxy_balancer.c index af409f67a2c..d45fab8d1aa 100644 --- a/modules/proxy/mod_proxy_balancer.c +++ b/modules/proxy/mod_proxy_balancer.c @@ -218,147 +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; - - /* 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; - - /* 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) { @@ -657,15 +516,10 @@ static int balancer_handler(request_rec *r) bsel->max_attempts_set = 1; } if ((val = apr_table_get(params, "lm"))) { - struct proxy_balancer_method *ent = - (struct proxy_balancer_method *) conf->lbmethods->elts; - int i; - for (i = 0; i < conf->lbmethods->nelts; i++) { - if (!strcasecmp(val, ent->name)) { - bsel->lbmethod = ent; - break; - } - ent++; + proxy_balancer_method *provider; + provider = ap_lookup_provider(PROXY_LBMETHOD, val, "0"); + if (provider) { + bsel->lbmethod = provider; } } } @@ -836,14 +690,16 @@ static int balancer_handler(request_rec *r) bsel->max_attempts); ap_rputs("LB Method:\n", r); @@ -879,29 +735,175 @@ static void child_init(apr_pool_t *p, server_rec *s) } +/* + * 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 - * the proxy_hook_load_lbmethods hook - * (eg: add_lbmethods below). + * 2. Register it as a provider. */ -static int add_lbmethods(proxy_server_conf *conf) +static const proxy_balancer_method byrequests = { - 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; + "byrequests", + &find_best_byrequests, + NULL +}; - return OK; -} +static const proxy_balancer_method bytraffic = +{ + "bytraffic", + &find_best_bytraffic, + NULL +}; static void ap_proxy_balancer_register_hook(apr_pool_t *p) { @@ -916,7 +918,8 @@ 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); + ap_register_provider(p, PROXY_LBMETHOD, "bytraffic", "0", &bytraffic); + ap_register_provider(p, PROXY_LBMETHOD, "byrequests", "0", &byrequests); } module AP_MODULE_DECLARE_DATA proxy_balancer_module = { diff --git a/modules/proxy/proxy_util.c b/modules/proxy/proxy_util.c index b12a955edb6..08f7f85a1b3 100644 --- a/modules/proxy/proxy_util.c +++ b/modules/proxy/proxy_util.c @@ -1155,7 +1155,6 @@ PROXY_DECLARE(const char *) ap_proxy_add_balancer(proxy_balancer **balancer, const char *url) { char *c, *q, *uri = apr_pstrdup(p, url); - int i; proxy_balancer_method *lbmethod; c = strchr(uri, ':'); @@ -1173,12 +1172,9 @@ PROXY_DECLARE(const char *) ap_proxy_add_balancer(proxy_balancer **balancer, * NOTE: The default method is byrequests, which we assume * exists! */ - lbmethod = (proxy_balancer_method *)conf->lbmethods->elts; - for (i = 0; i < conf->lbmethods->nelts; i++) { - if (!strcasecmp(lbmethod->name, "byrequests")) { - break; - } - lbmethod++; + lbmethod = ap_lookup_provider(PROXY_LBMETHOD, "byrequests", "0"); + if (!lbmethod) { + return "Can't find 'byrequests' lb method"; } (*balancer)->name = uri;