diff options
author | Jim Jagielski <jim@apache.org> | 2005-08-12 14:47:04 +0200 |
---|---|---|
committer | Jim Jagielski <jim@apache.org> | 2005-08-12 14:47:04 +0200 |
commit | a7d488a6d24dcae6c110d9c86dbe0383ca181626 (patch) | |
tree | cc7406301354555b464c8732bf76110ac487c2cd | |
parent | * modules/cache/cache_storage.c (cache_remove_url): Remove unused (diff) | |
download | apache2-a7d488a6d24dcae6c110d9c86dbe0383ca181626.tar.xz apache2-a7d488a6d24dcae6c110d9c86dbe0383ca181626.zip |
simple, functional interface to add additional balancer lb selection methods
without requiring code changes to mod_proxy/mod_proxy_balancer;
these can be implemented via sub-modules now.
Let the games begin...
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@232282 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r-- | CHANGES | 5 | ||||
-rw-r--r-- | modules/proxy/mod_proxy.c | 39 | ||||
-rw-r--r-- | modules/proxy/mod_proxy.h | 25 | ||||
-rw-r--r-- | modules/proxy/mod_proxy_balancer.c | 106 | ||||
-rw-r--r-- | modules/proxy/proxy_util.c | 16 |
5 files changed, 134 insertions, 57 deletions
@@ -1,6 +1,11 @@ -*- coding: utf-8 -*- Changes with Apache 2.3.0 + *) mod_proxy/mod_proxy_balancer: Provide a simple, functional + interface to add additional balancer lb selection methods + without requiring code changes to mod_proxy/mod_proxy_balancer; + these can be implemented via sub-modules now. [Jim Jagielski] + *) mod_cache: Fix incorrectly served 304 responses when expired cache entity is valid, but cache is unwritable and headers cannot be updated. [Colm MacCarthaigh <colm stdlib.net>] diff --git a/modules/proxy/mod_proxy.c b/modules/proxy/mod_proxy.c index fc1171ed89..1f3de0c117 100644 --- a/modules/proxy/mod_proxy.c +++ b/modules/proxy/mod_proxy.c @@ -224,7 +224,8 @@ static const char *set_worker_param(apr_pool_t *p, return NULL; } -static const char *set_balancer_param(apr_pool_t *p, +static const char *set_balancer_param(proxy_server_conf *conf, + apr_pool_t *p, proxy_balancer *balancer, const char *key, const char *val) @@ -272,13 +273,17 @@ static const char *set_balancer_param(apr_pool_t *p, balancer->max_attempts_set = 1; } else if (!strcasecmp(key, "lbmethod")) { - /* Which LB scheduler method */ - if (!strcasecmp(val, "traffic")) - balancer->lbmethod = lbmethod_traffic; - else if (!strcasecmp(val, "requests")) - balancer->lbmethod = lbmethod_requests; - else - return "lbmethod must be Traffic|Requests"; + 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++; + } + return "unknown lbmethod"; } else { return "unknown Balancer parameter"; @@ -793,6 +798,7 @@ 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; @@ -815,6 +821,9 @@ 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; } @@ -832,6 +841,7 @@ 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; @@ -1021,7 +1031,7 @@ static const char * return apr_pstrcat(cmd->temp_pool, "ProxyPass ", err, NULL); } for (i = 0; i < arr->nelts; i++) { - const char *err = set_balancer_param(cmd->pool, balancer, elts[i].key, + const char *err = set_balancer_param(conf, cmd->pool, balancer, elts[i].key, elts[i].val); if (err) return apr_pstrcat(cmd->temp_pool, "ProxyPass ", err, NULL); @@ -1509,7 +1519,7 @@ static const char * if (worker) err = set_worker_param(cmd->pool, worker, word, val); else - err = set_balancer_param(cmd->pool, balancer, word, val); + err = set_balancer_param(conf, cmd->pool, balancer, word, val); if (err) return apr_pstrcat(cmd->temp_pool, "ProxySet ", err, " ", word, " ", name, NULL); @@ -1754,9 +1764,7 @@ static int proxy_status_hook(request_rec *r, int flags) ap_rprintf(r, "</td><td>%" APR_TIME_T_FMT "</td>", apr_time_sec(balancer->timeout)); ap_rprintf(r, "<td>%s</td>\n", - balancer->lbmethod == lbmethod_requests ? "Requests" : - balancer->lbmethod == lbmethod_traffic ? "Traffic" : - "Unknown"); + balancer->lbmethod->name); ap_rputs("</table>\n", r); ap_rputs("\n\n<table border=\"0\"><tr>" "<th>Sch</th><th>Host</th><th>Stat</th>" @@ -1917,6 +1925,7 @@ 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) ) @@ -1942,6 +1951,10 @@ 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 55e1eaf7e3..43b3526617 100644 --- a/modules/proxy/mod_proxy.h +++ b/modules/proxy/mod_proxy.h @@ -120,6 +120,7 @@ struct noproxy_entry { typedef struct proxy_balancer proxy_balancer; typedef struct proxy_worker proxy_worker; typedef struct proxy_conn_pool proxy_conn_pool; +typedef struct proxy_balancer_method proxy_balancer_method; typedef struct { apr_array_header_t *proxies; @@ -179,6 +180,7 @@ 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; @@ -257,6 +259,7 @@ typedef struct { apr_size_t elected; /* Number of times the worker was elected */ char route[PROXY_WORKER_MAX_ROUTE_SIZ+1]; char redirect[PROXY_WORKER_MAX_ROUTE_SIZ+1]; + void *context; /* general purpose storage */ } proxy_worker_stat; /* Worker configuration */ @@ -293,6 +296,7 @@ struct proxy_worker { #if APR_HAS_THREADS apr_thread_mutex_t *mutex; /* Thread lock for updating address cache */ #endif + void *context; /* general purpose storage */ }; struct proxy_balancer { @@ -303,10 +307,7 @@ struct proxy_balancer { apr_interval_time_t timeout; /* Timeout for waiting on free connection */ int max_attempts; /* Number of attempts before failing */ char max_attempts_set; - enum { - lbmethod_requests = 1, - lbmethod_traffic = 2 - } lbmethod; + proxy_balancer_method *lbmethod; /* XXX: Perhaps we will need the proc mutex too. * Altrough we are only using arithmetic operations @@ -316,6 +317,14 @@ struct proxy_balancer { #if APR_HAS_THREADS apr_thread_mutex_t *mutex; /* Thread lock for updating lb params */ #endif + void *context; /* general purpose storage */ +}; + +struct proxy_balancer_method { + const char *name; /* name of the load balancer method*/ + proxy_worker *(*finder)(proxy_balancer *balancer, + request_rec *r); + void *context; /* general purpose storage */ }; #if APR_HAS_THREADS @@ -365,6 +374,14 @@ 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 diff --git a/modules/proxy/mod_proxy_balancer.c b/modules/proxy/mod_proxy_balancer.c index 28e03bbc8d..38314b26df 100644 --- a/modules/proxy/mod_proxy_balancer.c +++ b/modules/proxy/mod_proxy_balancer.c @@ -21,6 +21,7 @@ #include "mod_proxy.h" #include "ap_mpm.h" #include "apr_version.h" +#include "apr_hooks.h" module AP_MODULE_DECLARE_DATA proxy_balancer_module; @@ -262,13 +263,14 @@ static proxy_worker *find_session_route(proxy_balancer *balancer, * b a d c d a c d b d ... * */ + static proxy_worker *find_best_byrequests(proxy_balancer *balancer, - request_rec *r) + request_rec *r) { int i; int total_factor = 0; proxy_worker *worker = (proxy_worker *)balancer->workers->elts; - proxy_worker *candidate = NULL; + proxy_worker *mycandidate = NULL; /* First try to see if we have available candidate */ for (i = 0; i < balancer->workers->nelts; i++) { @@ -286,18 +288,18 @@ static proxy_worker *find_best_byrequests(proxy_balancer *balancer, if (PROXY_WORKER_IS_USABLE(worker)) { worker->s->lbstatus += worker->s->lbfactor; total_factor += worker->s->lbfactor; - if (!candidate || worker->s->lbstatus > candidate->s->lbstatus) - candidate = worker; + if (!mycandidate || worker->s->lbstatus > mycandidate->s->lbstatus) + mycandidate = worker; } worker++; } - if (candidate) { - candidate->s->lbstatus -= total_factor; - candidate->s->elected++; + if (mycandidate) { + mycandidate->s->lbstatus -= total_factor; + mycandidate->s->elected++; } - return candidate; + return mycandidate; } /* @@ -318,13 +320,13 @@ static proxy_worker *find_best_byrequests(proxy_balancer *balancer, * chosen more often, to even things out. */ static proxy_worker *find_best_bytraffic(proxy_balancer *balancer, - request_rec *r) + 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 *candidate = NULL; + proxy_worker *mycandidate = NULL; /* First try to see if we have available candidate */ for (i = 0; i < balancer->workers->nelts; i++) { @@ -342,19 +344,19 @@ static proxy_worker *find_best_bytraffic(proxy_balancer *balancer, if (PROXY_WORKER_IS_USABLE(worker)) { mytraffic = (worker->s->transferred/worker->s->lbfactor) + (worker->s->read/worker->s->lbfactor); - if (!candidate || mytraffic < curmin) { - candidate = worker; + if (!mycandidate || mytraffic < curmin) { + mycandidate = worker; curmin = mytraffic; } } worker++; } - if (candidate) { - candidate->s->elected++; + if (mycandidate) { + mycandidate->s->elected++; } - return candidate; + return mycandidate; } static proxy_worker *find_best_worker(proxy_balancer *balancer, @@ -365,14 +367,12 @@ static proxy_worker *find_best_worker(proxy_balancer *balancer, if (PROXY_THREAD_LOCK(balancer) != APR_SUCCESS) return NULL; - if (balancer->lbmethod == lbmethod_requests) { - candidate = find_best_byrequests(balancer, r); - } else if (balancer->lbmethod == lbmethod_traffic) { - candidate = find_best_bytraffic(balancer, r); - } else { + candidate = (*balancer->lbmethod->finder)(balancer, r); + +/* PROXY_THREAD_UNLOCK(balancer); return NULL; - } +*/ PROXY_THREAD_UNLOCK(balancer); @@ -657,18 +657,15 @@ static int balancer_handler(request_rec *r) bsel->max_attempts_set = 1; } if ((val = apr_table_get(params, "lm"))) { - int ival = atoi(val); - switch(ival) { - case 0: - break; - case lbmethod_traffic: - bsel->lbmethod = lbmethod_traffic; - break; - case lbmethod_requests: - bsel->lbmethod = lbmethod_requests; - break; - default: + 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++; } } } @@ -755,8 +752,7 @@ static int balancer_handler(request_rec *r) apr_time_sec(balancer->timeout)); ap_rprintf(r, "<td>%d</td>\n", balancer->max_attempts); ap_rprintf(r, "<td>%s</td>\n", - balancer->lbmethod == lbmethod_requests ? "Requests" : - balancer->lbmethod == lbmethod_traffic ? "Traffic" : "Unknown"); + balancer->lbmethod->name); ap_rputs("</table>\n", r); ap_rputs("\n\n<table border=\"0\"><tr>" "<th>Scheme</th><th>Host</th>" @@ -834,10 +830,17 @@ static int balancer_handler(request_rec *r) ap_rprintf(r, "value=\"%d\"></td></tr>\n", bsel->max_attempts); ap_rputs("<tr><td>LB Method:</td><td><select name=\"lm\">", r); - ap_rprintf(r, "<option value=\"%d\" %s>Requests</option>", lbmethod_requests, - bsel->lbmethod == lbmethod_requests ? "selected" : ""); - ap_rprintf(r, "<option value=\"%d\" %s>Traffic</option>", lbmethod_traffic, - bsel->lbmethod == lbmethod_traffic ? "selected" : ""); + { + struct proxy_balancer_method *ent = + (struct proxy_balancer_method *) conf->lbmethods->elts; + int i; + for (i = 0; i < conf->lbmethods->nelts; i++) { + ap_rprintf(r, "<option value=\"%s\" %s>%s</option>", ent->name, + (!strcasecmp(bsel->lbmethod->name, ent->name)) ? "selected" : "", + ent->name); + ent++; + } + } ap_rputs("</select></td></tr>\n", r); ap_rputs("<tr><td colspan=2><input type=submit value=\"Submit\"></td></tr>\n", r); ap_rvputs(r, "</table>\n<input type=hidden name=\"b\" ", NULL); @@ -871,6 +874,30 @@ 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. @@ -880,10 +907,11 @@ static void ap_proxy_balancer_register_hook(apr_pool_t *p) static const char *const aszPred[] = { "mpm_winnt.c", "mod_proxy.c", NULL}; /* manager handler */ ap_hook_handler(balancer_handler, NULL, NULL, APR_HOOK_FIRST); - ap_hook_child_init(child_init, aszPred, NULL, APR_HOOK_MIDDLE); + ap_hook_child_init(child_init, aszPred, NULL, APR_HOOK_MIDDLE); 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 f975dc0ea2..6bcb559b55 100644 --- a/modules/proxy/proxy_util.c +++ b/modules/proxy/proxy_util.c @@ -1155,6 +1155,8 @@ 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, ':'); if (c == NULL || c[1] != '/' || c[2] != '/' || c[3] == '\0') @@ -1167,8 +1169,20 @@ PROXY_DECLARE(const char *) ap_proxy_add_balancer(proxy_balancer **balancer, *balancer = apr_array_push(conf->balancers); memset(*balancer, 0, sizeof(proxy_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++; + } + (*balancer)->name = uri; - (*balancer)->lbmethod = lbmethod_requests; + (*balancer)->lbmethod = lbmethod; (*balancer)->workers = apr_array_make(p, 5, sizeof(proxy_worker)); /* XXX Is this a right place to create mutex */ #if APR_HAS_THREADS |