From: Mladen Turk Date: Thu, 26 Aug 2004 06:53:39 +0000 (+0000) Subject: Add dynamic management to load balancer: X-Git-Tag: STRIKER_2_1_0_RC1~29 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2d7f11c8035b26a244adc99df9d7a301f18c7107;p=thirdparty%2Fapache%2Fhttpd.git Add dynamic management to load balancer: SetHandler balancer-manager It enables changing load factors, session routes, redirection routes, and disabling/enabling particular workers. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@104812 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/modules/proxy/proxy_balancer.c b/modules/proxy/proxy_balancer.c index 309ddc7713e..a5c7ea028d0 100644 --- a/modules/proxy/proxy_balancer.c +++ b/modules/proxy/proxy_balancer.c @@ -372,8 +372,301 @@ static int proxy_balancer_post_request(proxy_worker *worker, return OK; } +static void recalc_factors(proxy_balancer *balancer, + proxy_runtime_worker *fixed) +{ + int i; + double median, ffactor = 0.0; + proxy_runtime_worker *workers; + + + /* Recalculate lbfactors */ + workers = (proxy_runtime_worker *)balancer->workers->elts; + /* Special case if there is only one worker it's + * load factor will always be 100 + */ + if (balancer->workers->nelts == 1) { + workers->s->lbstatus = workers->s->lbfactor = 100.0; + return; + } + for (i = 0; i < balancer->workers->nelts; i++) { + if (workers[i].s->lbfactor > 100.0) + workers[i].s->lbfactor = 100.0; + ffactor += workers[i].s->lbfactor; + } + if (ffactor < 100.0) { + median = (100.0 - ffactor) / (balancer->workers->nelts - 1); + for (i = 0; i < balancer->workers->nelts; i++) { + if (&(workers[i]) != fixed) + workers[i].s->lbfactor += median; + } + } + else if (fixed->s->lbfactor < 100.0) { + median = (ffactor - 100.0) / (balancer->workers->nelts - 1); + for (i = 0; i < balancer->workers->nelts; i++) { + if (workers[i].s->lbfactor > median && + &(workers[i]) != fixed) + workers[i].s->lbfactor -= median; + } + } + else { + median = (ffactor - 100.0) / balancer->workers->nelts; + for (i = 0; i < balancer->workers->nelts; i++) { + workers[i].s->lbfactor -= median; + } + } + for (i = 0; i < balancer->workers->nelts; i++) { + /* Update the status entires */ + workers[i].s->lbstatus = workers[i].s->lbfactor; + } +} + +/* Invoke handler */ +static int balancer_handler(request_rec *r) +{ + void *sconf = r->server->module_config; + proxy_server_conf *conf = (proxy_server_conf *) + ap_get_module_config(sconf, &proxy_module); + apr_array_header_t *proxies = conf->proxies; + struct proxy_remote *ents = (struct proxy_remote *)proxies->elts; + proxy_balancer *balancer, *bsel = NULL; + proxy_runtime_worker *worker, *wsel = NULL; + apr_table_t *params = apr_table_make(r->pool, 10); + int access_status; + int i, n; + const char *name; + + /* is this for us? */ + if (strcmp(r->handler, "balancer-manager")) + return DECLINED; + r->allowed = (AP_METHOD_BIT << M_GET); + if (r->method_number != M_GET) + return DECLINED; + + if (r->args) { + char *args = apr_pstrdup(r->pool, r->args); + char *tok, *val; + while (args && *args) { + if ((val = ap_strchr_c(args, '='))) { + *val++ = '\0'; + if ((tok = ap_strchr_c(val, '&'))) + *tok++ = '\0'; + if ((access_status = ap_unescape_url(val)) != OK) + return access_status; + apr_table_setn(params, args, val); + args = tok; + } + else + return HTTP_BAD_REQUEST; + } + } + if ((name = apr_table_get(params, "b"))) + bsel = ap_proxy_get_balancer(r->pool, conf, + apr_pstrcat(r->pool, "balancer://", name, NULL)); + if ((name = apr_table_get(params, "w"))) { + const char *sc = apr_table_get(params, "s"); + char *asname = NULL; + proxy_worker *ws = NULL; + if (sc) { + asname = apr_pstrcat(r->pool, sc, "://", name, NULL); + ws = ap_proxy_get_worker(r->pool, conf, asname); + } + if (ws) { + worker = (proxy_runtime_worker *)bsel->workers->elts; + for (n = 0; n < bsel->workers->nelts; n++) { + if (strcasecmp(worker->w->name, ws->name) == 0) { + wsel = worker; + break; + } + ++worker; + } + } + } + /* First set the params */ + if (bsel) { + const char *val; + if ((val = apr_table_get(params, "ss"))) { + if (strlen(val)) + bsel->sticky = apr_pstrdup(conf->pool, val); + else + bsel->sticky = NULL; + } + if ((val = apr_table_get(params, "tm"))) { + int ival = atoi(val); + if (ival >= 0) + bsel->timeout = apr_time_from_sec(ival); + } + } + if (wsel) { + const char *val; + if ((val = apr_table_get(params, "lf"))) { + char *ep; + double dval = strtod(val, &ep); + if (dval > 1) { + wsel->s->lbfactor = dval; + if (bsel) + recalc_factors(bsel, wsel); + } + } + if ((val = apr_table_get(params, "wr"))) { + if (strlen(val)) + wsel->w->route = apr_pstrdup(conf->pool, val); + else + wsel->w->route = NULL; + } + if ((val = apr_table_get(params, "rr"))) { + if (strlen(val)) + wsel->w->redirect = apr_pstrdup(conf->pool, val); + else + wsel->w->redirect = NULL; + } + if ((val = apr_table_get(params, "dw"))) + wsel->w->status |= PROXY_WORKER_DISABLED; + else + wsel->w->status &= ~PROXY_WORKER_DISABLED; + + } + if (apr_table_get(params, "xml")) { + ap_set_content_type(r, "text/xml"); + ap_rputs("\n", r); + ap_rputs("\n", r); + ap_rputs(" \n", r); + balancer = (proxy_balancer *)conf->balancers->elts; + for (i = 0; i < conf->balancers->nelts; i++) { + ap_rputs(" \n", r); + ap_rvputs(r, " ", balancer->name, "\n", NULL); + ap_rputs(" \n", r); + worker = (proxy_runtime_worker *)balancer->workers->elts; + for (n = 0; n < balancer->workers->nelts; n++) { + ap_rputs(" \n", r); + ap_rvputs(r, " ", worker->w->scheme, + "\n", NULL); + ap_rvputs(r, " ", worker->w->hostname, + "\n", NULL); + ap_rprintf(r, " %.2f\n", + worker->s->lbfactor); + ap_rputs(" \n", r); + ++worker; + } + ap_rputs(" \n", r); + ap_rputs(" \n", r); + ++balancer; + } + ap_rputs(" \n", r); + ap_rputs("", r); + } + else { + ap_set_content_type(r, "text/html"); + ap_rputs(DOCTYPE_HTML_3_2 + "Balancer Manager\n", r); + ap_rputs("

Load Balancer Manager for ", r); + ap_rvputs(r, ap_get_server_name(r), "

\n\n", NULL); + ap_rvputs(r, "
Server Version: ", + ap_get_server_version(), "
\n", NULL); + ap_rvputs(r, "
Server Built: ", + ap_get_server_built(), "\n
\n", NULL); + balancer = (proxy_balancer *)conf->balancers->elts; + for (i = 0; i < conf->balancers->nelts; i++) { + ap_rputs("
\n

LoadBalancer Status for ", r); + ap_rvputs(r, "uri, "?b=", + balancer->name + sizeof("balancer://") - 1, + "\">", NULL); + ap_rvputs(r, balancer->name, "

\n\n", NULL); + ap_rputs("\n\n" + "" + "\n", r); + ap_rvputs(r, "\n", + apr_time_sec(balancer->timeout)); + ap_rputs("
StickySesionTimeout
", balancer->sticky, NULL); + ap_rprintf(r, "%" APR_TIME_T_FMT "
\n", r); + ap_rputs("\n\n" + "" + "" + "" + "\n", r); + + worker = (proxy_runtime_worker *)balancer->workers->elts; + for (n = 0; n < balancer->workers->nelts; n++) { + + ap_rvputs(r, "\n", NULL); + ap_rvputs(r, "\n", r); + + ++worker; + } + ap_rputs("
SchemeHostRouteRouteRedirFactorStatus
", worker->w->scheme, "", NULL); + ap_rvputs(r, "uri, "?b=", + balancer->name + sizeof("balancer://") - 1, + "&s=", worker->w->scheme, "&w=", worker->w->hostname, + "\">", NULL); + ap_rvputs(r, worker->w->hostname, "", worker->w->route, NULL); + ap_rvputs(r, "", worker->w->redirect, NULL); + ap_rprintf(r, "%.2f", worker->s->lbfactor); + if (worker->w->status & PROXY_WORKER_DISABLED) + ap_rputs("Dis", r); + else if (worker->w->status & PROXY_WORKER_IN_ERROR) + ap_rputs("Err", r); + else if (worker->w->status & PROXY_WORKER_INITIALIZED) + ap_rputs("Ok", r); + else + ap_rputs("-", r); + ap_rputs("
\n", r); + ++balancer; + } + ap_rputs("
\n", r); + if (wsel && bsel) { + ap_rputs("

Edit worker settings for ", r); + ap_rvputs(r, wsel->w->name, "

\n", NULL); + ap_rvputs(r, "
uri, "\">\n
", NULL); + ap_rputs("\n", wsel->s->lbfactor); + ap_rputs("\n", r); + ap_rputs("\n", r); + ap_rputs("\n", r); + ap_rputs("\n", r); + ap_rvputs(r, "
Load factor:
Route:w->route, NULL); + ap_rputs("\">
Route Redirect:w->redirect, NULL); + ap_rputs("\">
Disabled:w->status & PROXY_WORKER_DISABLED) + ap_rputs(" checked", r); + ap_rputs(">
\nw->scheme, "\">\n", NULL); + ap_rvputs(r, "w->hostname, "\">\n", NULL); + ap_rvputs(r, "name + sizeof("balancer://") - 1, + "\">\n\n", NULL); + ap_rputs("
\n", r); + } + else if (bsel) { + ap_rputs("

Edit balancer settings for ", r); + ap_rvputs(r, bsel->name, "

\n", NULL); + ap_rvputs(r, "
uri, "\">\n
", NULL); + ap_rputs("\n\n", + apr_time_sec(bsel->timeout)); + ap_rputs("\n", r); + ap_rvputs(r, "
StickySession Identifier:sticky) + ap_rvputs(r, "value=\"", bsel->sticky, "\"", NULL); + ap_rputs(">
Timeout:
\nname + sizeof("balancer://") - 1, + "\">\n\n", NULL); + ap_rputs("
\n", r); + } + ap_rputs(ap_psignature("",r), r); + ap_rputs("\n", r); + } + return OK; +} + static void ap_proxy_balancer_register_hook(apr_pool_t *p) { + /* manager handler */ + ap_hook_handler(balancer_handler, NULL, NULL, APR_HOOK_FIRST); 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); }