Commit 7d8505c9 authored by Jim Jagielski's avatar Jim Jagielski
Browse files

Add in a very simple balancer "set" concept, which allows

for members to be assigned to a particular cluster set
such that members in lower-numbered sets are checked/used
before those in higher ones.

Also bundled in this are some HTML cleanups for the balancer
manager UI. Sorry for the mixins :)

Compiles/builds clean: passes test framework as well
as more normal usage tests ;)


git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@427172 13f79535-47bb-0310-9956-ffa450edef68
parent ab001123
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -2,6 +2,10 @@
Changes with Apache 2.3.0
  [Remove entries to the current 2.0 and 2.2 section below, when backported]
  *) mod_proxy_balancer: Workers can now be defined as part of
     a balancer cluster "set" in which members of a lower-numbered set
     are preferred over higher numbered ones. [Jim Jagielski]
  *) SECURITY: CVE-2006-3747 (cve.mitre.org)
     mod_rewrite: Fix an off-by-one security problem in the ldap scheme
     handling.  For some RewriteRules this could lead to a pointer being
+8 −1
Original line number Diff line number Diff line
@@ -253,6 +253,12 @@ static const char *set_worker_param(apr_pool_t *p,
        worker->ping_timeout = apr_time_from_sec(ival);
        worker->ping_timeout_set = 1;
    }
    else if (!strcasecmp(key, "lbset")) {
        ival = atoi(val);
        if (ival < 0 || ival > 99)
            return "lbset must be between 0 and 99";
        worker->lbset = ival;
    }
    else {
        return "unknown Worker parameter";
    }
@@ -1898,7 +1904,7 @@ static int proxy_status_hook(request_rec *r, int flags)
        ap_rputs("\n\n<table border=\"0\"><tr>"
                 "<th>Sch</th><th>Host</th><th>Stat</th>"
                 "<th>Route</th><th>Redir</th>"
                 "<th>F</th><th>Acc</th><th>Wr</th><th>Rd</th>"
                 "<th>F</th><th>Set</th><th>Acc</th><th>Wr</th><th>Rd</th>"
                 "</tr>\n", r);

        worker = (proxy_worker *)balancer->workers->elts;
@@ -1917,6 +1923,7 @@ static int proxy_status_hook(request_rec *r, int flags)
            ap_rvputs(r, "</td><td>", worker->s->route, NULL);
            ap_rvputs(r, "</td><td>", worker->s->redirect, NULL);
            ap_rprintf(r, "</td><td>%d</td>", worker->s->lbfactor);
            ap_rprintf(r, "<td>%d</td>", worker->s->lbset);
            ap_rprintf(r, "<td>%" APR_SIZE_T_FMT "</td><td>", worker->s->elected);
            ap_rputs(apr_strfsize(worker->s->transferred, fbuf), r);
            ap_rputs("</td><td>", r);
+15 −12
Original line number Diff line number Diff line
@@ -289,6 +289,8 @@ typedef struct {
    char            route[PROXY_WORKER_MAX_ROUTE_SIZ+1];
    char            redirect[PROXY_WORKER_MAX_ROUTE_SIZ+1];
    void            *context;   /* general purpose storage */
    apr_size_t      busy;       /* busyness factor */
    int             lbset;      /* load balancer cluster set */
} proxy_worker_stat;

/* Worker configuration */
@@ -334,6 +336,7 @@ struct proxy_worker {
    int             flush_wait;  /* poll wait time in microseconds if flush_auto */
    apr_interval_time_t ping_timeout;
    char ping_timeout_set;
    int             lbset;      /* load balancer cluster set */
};

/*
+91 −58
Original line number Diff line number Diff line
@@ -100,6 +100,7 @@ static int init_balancer_members(proxy_server_conf *conf, server_rec *s,
        /* Set to the original configuration */
        workers[i].s->lbstatus = workers[i].s->lbfactor =
          (workers[i].lbfactor ? workers[i].lbfactor : 1);
        workers[i].s->lbset = workers[i].lbset;
    }
    /* Set default number of attempts to the number of
     * workers.
@@ -622,6 +623,12 @@ static int balancer_handler(request_rec *r)
            else if (!strcasecmp(val, "Enable"))
                wsel->s->status &= ~PROXY_WORKER_DISABLED;
        }
        if ((val = apr_table_get(params, "ls"))) {
            int ival = atoi(val);
            if (ival >= 0 && ival <= 99) {
                wsel->s->lbset = ival;
             }
        }

    }
    if (apr_table_get(params, "xml")) {
@@ -684,13 +691,13 @@ static int balancer_handler(request_rec *r)
            ap_rputs("\n\n<table border=\"0\" style=\"text-align: left;\"><tr>"
                "<th>Worker URL</th>"
                "<th>Route</th><th>RouteRedir</th>"
                "<th>Factor</th><th>Status</th>"
                "<th>Factor</th><th>Set</th><th>Status</th>"
                "<th>Elected</th><th>To</th><th>From</th>"
                "</tr>\n", r);

            worker = (proxy_worker *)balancer->workers->elts;
            for (n = 0; n < balancer->workers->nelts; n++) {

                char fbuf[50];
                ap_rvputs(r, "<tr>\n<td><a href=\"", r->uri, "?b=",
                          balancer->name + sizeof("balancer://") - 1, "&w=",
                          ap_escape_uri(r->pool, worker->name),
@@ -698,7 +705,8 @@ static int balancer_handler(request_rec *r)
                ap_rvputs(r, worker->name, "</a></td>", NULL);
                ap_rvputs(r, "<td>", worker->s->route, NULL);
                ap_rvputs(r, "</td><td>", worker->s->redirect, NULL);
                ap_rprintf(r, "</td><td>%d</td><td>", worker->s->lbfactor);
                ap_rprintf(r, "</td><td>%d</td>", worker->s->lbfactor);
                ap_rprintf(r, "<td>%d</td><td>", worker->s->lbset);
                if (worker->s->status & PROXY_WORKER_DISABLED)
                   ap_rputs("Dis ", r);
                if (worker->s->status & PROXY_WORKER_IN_ERROR)
@@ -712,10 +720,11 @@ static int balancer_handler(request_rec *r)
                if (!PROXY_WORKER_IS_INITIALIZED(worker))
                    ap_rputs("-", r);
                ap_rputs("</td>", r);
                ap_rprintf(r, "<td>%" APR_SIZE_T_FMT "</td>", worker->s->elected);
                ap_rprintf(r, "<td>%" APR_OFF_T_FMT "</td>", worker->s->transferred);
                ap_rprintf(r, "<td>%" APR_OFF_T_FMT "</td>", worker->s->read);
                ap_rputs("</tr>\n", r);
                ap_rprintf(r, "<td>%" APR_SIZE_T_FMT "</td><td>", worker->s->elected);
                ap_rputs(apr_strfsize(worker->s->transferred, fbuf), r);
                ap_rputs("</td><td>", r);
                ap_rputs(apr_strfsize(worker->s->read, fbuf), r);
                ap_rputs("</td></tr>\n", r);

                ++worker;
            }
@@ -729,20 +738,22 @@ static int balancer_handler(request_rec *r)
            ap_rvputs(r, "<form method=\"GET\" action=\"", NULL);
            ap_rvputs(r, r->uri, "\">\n<dl>", NULL);
            ap_rputs("<table><tr><td>Load factor:</td><td><input name=\"lf\" type=text ", r);
            ap_rprintf(r, "value=\"%d\"></td><tr>\n", wsel->s->lbfactor);
            ap_rprintf(r, "value=\"%d\"></td></tr>\n", wsel->s->lbfactor);
            ap_rputs("<tr><td>LB Set:</td><td><input name=\"ls\" type=text ", r);
            ap_rprintf(r, "value=\"%d\"></td></tr>\n", wsel->s->lbset);
            ap_rputs("<tr><td>Route:</td><td><input name=\"wr\" type=text ", r);
            ap_rvputs(r, "value=\"", wsel->route, NULL);
            ap_rputs("\"></td><tr>\n", r);
            ap_rputs("\"></td></tr>\n", r);
            ap_rputs("<tr><td>Route Redirect:</td><td><input name=\"rr\" type=text ", r);
            ap_rvputs(r, "value=\"", wsel->redirect, NULL);
            ap_rputs("\"></td><tr>\n", r);
            ap_rputs("\"></td></tr>\n", r);
            ap_rputs("<tr><td>Status:</td><td>Disabled: <input name=\"dw\" value=\"Disable\" type=radio", r);
            if (wsel->s->status & PROXY_WORKER_DISABLED)
                ap_rputs(" checked", r);
            ap_rputs("> | Enabled: <input name=\"dw\" value=\"Enable\" type=radio", r);
            if (!(wsel->s->status & PROXY_WORKER_DISABLED))
                ap_rputs(" checked", r);
            ap_rputs("></td><tr>\n", r);
            ap_rputs("></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=\"w\" ",  NULL);
            ap_rvputs(r, "value=\"", ap_escape_uri(r->pool, wsel->name), "\">\n", NULL);
@@ -867,15 +878,24 @@ static proxy_worker *find_best_byrequests(proxy_balancer *balancer,
    proxy_worker *mycandidate = NULL;
    int checking_standby = 0;
    int checked_standby = 0;
    int cur_lbset = 0;
    int max_lbset = 0;
    
    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 */
    do {
        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
@@ -898,6 +918,8 @@ static proxy_worker *find_best_byrequests(proxy_balancer *balancer,
            }
            checked_standby = checking_standby++;
        }
        cur_lbset++;
    } while (cur_lbset < max_lbset && !mycandidate);

    if (mycandidate) {
        mycandidate->s->lbstatus -= total_factor;
@@ -934,15 +956,24 @@ static proxy_worker *find_best_bytraffic(proxy_balancer *balancer,
    int checking_standby = 0;
    int checked_standby = 0;
    proxy_worker *mycandidate = NULL;
    int cur_lbset = 0;
    int max_lbset = 0;

    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 */
    do {
        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
@@ -967,6 +998,8 @@ static proxy_worker *find_best_bytraffic(proxy_balancer *balancer,
            }
            checked_standby = checking_standby++;
        }
        cur_lbset++;
    } while (cur_lbset < max_lbset && !mycandidate);

    if (mycandidate) {
        mycandidate->s->elected++;