Commit b24eecae authored by Jim Jagielski's avatar Jim Jagielski
Browse files

simplify the BalancerMember load factor weighting. Instead of

being percentages (and adjusting when the number don't add
up), loadfactors/lbfactors are now normalized values, so
values like:

   worker    a   b   c
   lbfactor  1   1   2

work as expected (ie: a gets 25%, b gets 25% and c gets 50%).
So we could also have the above as:

   worker    a   b   c
   lbfactor 25  25  50

or even

   worker    a   b   c
   lbfactor 15  15  30



git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@122551 13f79535-47bb-0310-9956-ffa450edef68
parent d03f939a
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -2,6 +2,10 @@ Changes with Apache 2.1.3
  [Remove entries to the current 2.0 section below, when backported]
  *) Significantly simplify the load balancer scheduling algorithm
     for the proxy BalancerMember weighting. loadfactors (lbfactors)
     are now normalized with respect to each other. [Jim Jagielski]
  *) mod_dumpio: Added to the available module suite. Placed in
     the (new) debug module subdirectory. mod_bucketeer moved to
     that directory as well. [Jim Jagielski]
+2 −2
Original line number Diff line number Diff line
@@ -91,8 +91,8 @@ static const char *set_worker_param(apr_pool_t *p,

    int ival;
    if (!strcasecmp(key, "loadfactor")) {
        /* Worker load factor. Used with BalancerMamber
         * It is a number between 1 and 100 in percents.
        /* Normalized load factor. Used with BalancerMamber,
         * it is a number between 1 and 100.
         */
        worker->lbfactor = atoi(val);
        if (worker->lbfactor < 1 || worker->lbfactor > 100)
+24 −92
Original line number Diff line number Diff line
@@ -27,7 +27,6 @@ static int init_balancer_members(proxy_server_conf *conf, server_rec *s,
                                 proxy_balancer *balancer)
{
    int i;
    int median, ffactor = 0;
    proxy_worker *workers;    

    workers = (proxy_worker *)balancer->workers->elts;
@@ -39,41 +38,10 @@ static int init_balancer_members(proxy_server_conf *conf, server_rec *s,
    }

    workers = (proxy_worker *)balancer->workers->elts;
    /* Recalculate lbfactors */
    for (i = 0; i < balancer->workers->nelts; i++) {
        /* Set to the original configuration */
        workers[i].s->lbfactor = workers[i].lbfactor;
        ffactor += workers[i].s->lbfactor;
    }
    if (ffactor < 100) {
        int z = 0;
        for (i = 0; i < balancer->workers->nelts; i++) {
            if (workers[i].s->lbfactor == 0) 
                ++z;
        }
        if (z) {
            median = (100 - ffactor) / z;
            for (i = 0; i < balancer->workers->nelts; i++) {
                if (workers[i].s->lbfactor == 0) 
                    workers[i].s->lbfactor = median;
            }
        }
        else {
            median = (100 - ffactor) / balancer->workers->nelts;
            for (i = 0; i < balancer->workers->nelts; i++)
                workers[i].s->lbfactor += median;
        }
    }
    else if (ffactor > 100) {
        median = (ffactor - 100) / balancer->workers->nelts;
        for (i = 0; i < balancer->workers->nelts; i++) {
            if (workers[i].s->lbfactor > median)
                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;
        workers[i].s->lbstatus = workers[i].s->lbfactor =
          (workers[i].lbfactor ? workers[i].lbfactor : 1);
    }
    return 0;
}
@@ -196,7 +164,7 @@ static proxy_worker *find_session_route(proxy_balancer *balancer,
 * The idea behind this scheduler is the following:
 *
 * lbfactor is "how much we expect this worker to work", or "the worker's
 * work quota".
 * normalized work quota".
 *
 * lbstatus is "how urgent this worker has to work to fulfill its quota
 * of work".
@@ -214,36 +182,28 @@ static proxy_worker *find_session_route(proxy_balancer *balancer,
 *
 * worker     a    b    c    d
 * lbfactor  25   25   25   25
 * lbstatus   0    0    0    0
 *
 * And b gets disabled, the following schedule is produced:
 *
 * lbstatus -50    0   25   25
 * lbstatus -25    0  -25   50
 * lbstatus   0    0    0    0
 * (repeat)
 *    a c d a c d a c d ...
 *
 * That is it schedules: a c d a c d a c d ...
 * Note that the above lbfactor setting is the *exact* same as:
 *
 * The following asymmetric configuration works as one would expect:
 * worker     a    b    c    d
 * lbfactor   1    1    1    1
 *
 * worker     a    b
 * lbfactor  70   30
 * Asymmetric configurations work as one would expect. For
 * example:
 *
 * lbstatus -30   30
 * lbstatus  40  -40
 * lbstatus  10  -10
 * lbstatus -20   20
 * lbstatus -50   50
 * lbstatus  20  -20
 * lbstatus -10   10
 * lbstatus -40   40
 * lbstatus  30  -30
 * lbasatus   0    0
 * (repeat)
 * 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 ...
 *
 * That is after 10 schedules, the schedule repeats and 7 a are selected
 * with 3 b interspersed.
 */
static proxy_worker *find_best_worker(proxy_balancer *balancer,
                                      request_rec *r)
@@ -461,51 +421,23 @@ static int proxy_balancer_post_request(proxy_worker *worker,
    return OK;
} 

static void recalc_factors(proxy_balancer *balancer,
                           proxy_worker *fixed)
static void recalc_factors(proxy_balancer *balancer)
{
    int i;
    int median, ffactor = 0;
    proxy_worker *workers;    


    /* Recalculate lbfactors */
    workers = (proxy_worker *)balancer->workers->elts;
    /* Special case if there is only one worker it's
     * load factor will always be 100
     * load factor will always be 1
     */
    if (balancer->workers->nelts == 1) {
        workers->s->lbstatus = workers->s->lbfactor = 100;
        workers->s->lbstatus = workers->s->lbfactor = 1;
        return;
    }
    for (i = 0; i < balancer->workers->nelts; i++) {
        if (workers[i].s->lbfactor > 100)
            workers[i].s->lbfactor = 100;
        ffactor += workers[i].s->lbfactor;
    }
    if (ffactor < 100) {
        median = (100 - 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) {
        median = (ffactor - 100) / (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) / 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 */
        /* Update the status entries */
        workers[i].s->lbstatus = workers[i].s->lbfactor;
    }
}
@@ -595,10 +527,10 @@ static int balancer_handler(request_rec *r)
        const char *val;
        if ((val = apr_table_get(params, "lf"))) {
            int ival = atoi(val);
            if (ival > 1) {
            if (ival >= 1 && ival <= 100) {
                wsel->s->lbfactor = ival;
                if (bsel)
                    recalc_factors(bsel, wsel);
                    recalc_factors(bsel);
            }
        }
        if ((val = apr_table_get(params, "wr"))) {