Commit 4ac0179f authored by Jim Jagielski's avatar Jim Jagielski
Browse files

Merge r420936, r420954, r420986, r421283 from trunk:

Restructure the find_route_worker() function. Basically,
it should take care of knowing about usable and unusable
workers. By centralizing this logic, it will make it
easier and more streamlined to add in the forthcoming
hot-standby status workers.

Clean up some proxy macros. Avoid the use of magic
numbers, and instead use pre-defined defines. Also,
ensure that usable workers have been initialized :)

Allocate a bit for hot standbys. Adjust so that
normal "usable" workers don't count these.

Add in hot-standby balancer member. If all other members
are disabled or not-usable, ONLY THEN will the hot
standby's be used.


Reviewed by: jim


git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.2.x@438563 13f79535-47bb-0310-9956-ffa450edef68
parent 698c0109
Loading
Loading
Loading
Loading
+5 −0
Changes for CHANGES: 5 added lines, 0 removed lines.
Original line number Diff line number Diff line
                                                        -*- coding: utf-8 -*-
Changes with Apache 2.2.4
  *) mod_proxy_balancer: Workers can now be defined as "hot standby" which
     will only be used if all other workers are unusable (eg: in
     error or disabled). Also, the balancer-manager displays the election
     count and I/O counts of all workers. [Jim Jagielski]
  *) mod_proxy_ajp: Close connection to backend if reading of request body
     fails. PR 40310. [Ian Abel <ianabel mxtelecom.com>]
+0 −10
Changes for STATUS: 0 added lines, 10 removed lines.
Original line number Diff line number Diff line
@@ -94,16 +94,6 @@ PATCHES ACCEPTED TO BACKPORT FROM TRUNK:
        Trunk version works
      +1: jim, mturk, rpluem

    * mod_proxy_balancer: Add in Hot Standby worker functionality.
      Trunk version of patch:
        http://svn.apache.org/viewvc?view=rev&revision=420936
        http://svn.apache.org/viewvc?view=rev&revision=420954
        http://svn.apache.org/viewvc?view=rev&revision=420986
        http://svn.apache.org/viewvc?view=rev&revision=421283
      2.2.x version of patch:
        http://people.apache.org/~jim/patches/hot-standby.txt
      +1: jim, mturk, rpluem

PATCHES PROPOSED TO BACKPORT FROM TRUNK:

    * mpm_winnt: Fix return values from wait_for_many_objects.
+7 −1
Changes for modules/proxy/mod_proxy.c: 7 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -213,8 +213,14 @@ static const char *set_worker_param(apr_pool_t *p,
                else
                    worker->status &= ~PROXY_WORKER_IN_ERROR;
            }
            else if (*v == 'H' || *v == 'h') {
                if (mode)
                    worker->status |= PROXY_WORKER_HOT_STANDBY;
                else
                    worker->status &= ~PROXY_WORKER_HOT_STANDBY;
            }
            else {
                return "Unknow status parameter option";
                return "Unknown status parameter option";
            }
        }
    }
+13 −2
Changes for modules/proxy/mod_proxy.h: 13 added lines, 2 removed lines.
Original line number Diff line number Diff line
@@ -241,15 +241,26 @@ struct proxy_conn_pool {
    proxy_conn_rec *conn;   /* Single connection for prefork mpm's */
};

/* woker status flags */
/* worker status flags */
#define PROXY_WORKER_INITIALIZED    0x0001
#define PROXY_WORKER_IGNORE_ERRORS  0x0002
#define PROXY_WORKER_IN_SHUTDOWN    0x0010
#define PROXY_WORKER_DISABLED       0x0020
#define PROXY_WORKER_STOPPED        0x0040
#define PROXY_WORKER_IN_ERROR       0x0080
#define PROXY_WORKER_HOT_STANDBY    0x0100

#define PROXY_WORKER_IS_USABLE(f)   (!((f)->s->status & 0x00F0))
#define PROXY_WORKER_NOT_USABLE_BITMAP ( PROXY_WORKER_IN_SHUTDOWN | \
PROXY_WORKER_DISABLED | PROXY_WORKER_STOPPED | PROXY_WORKER_IN_ERROR )

#define PROXY_WORKER_IS_INITIALIZED(f)   ( (f)->s->status & \
  PROXY_WORKER_INITIALIZED )

#define PROXY_WORKER_IS_STANDBY(f)   ( (f)->s->status & \
  PROXY_WORKER_HOT_STANDBY )

#define PROXY_WORKER_IS_USABLE(f)   ( !((f)->s->status & \
  (PROXY_WORKER_NOT_USABLE_BITMAP)) && PROXY_WORKER_IS_INITIALIZED(f) )

/* default worker retry timeout in seconds */
#define PROXY_WORKER_DEFAULT_RETRY  60
+83 −50
Changes for modules/proxy/mod_proxy_balancer.c: 83 added lines, 50 removed lines.
Original line number Diff line number Diff line
@@ -169,15 +169,63 @@ static char *get_cookie_param(request_rec *r, const char *name)
/* Find the worker that has the 'route' defined
 */
static proxy_worker *find_route_worker(proxy_balancer *balancer,
                                       const char *route)
                                       const char *route, request_rec *r)
{
    int i;
    proxy_worker *worker = (proxy_worker *)balancer->workers->elts;
    for (i = 0; i < balancer->workers->nelts; i++) {
    int checking_standby = 0;
    int checked_standby = 0;
    
    proxy_worker *worker;
    while (!checked_standby) {
        worker = (proxy_worker *)balancer->workers->elts;
        for (i = 0; i < balancer->workers->nelts; i++, worker++) {
            if ( (checking_standby ? !PROXY_WORKER_IS_STANDBY(worker) : PROXY_WORKER_IS_STANDBY(worker)) )
                continue;
            if (*(worker->s->route) && strcmp(worker->s->route, route) == 0) {
                if (worker && PROXY_WORKER_IS_USABLE(worker)) {
                    return worker;
                } else {
                    /*
                     * 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.
                     */
                    ap_proxy_retry_worker("BALANCER", worker, r->server);
                    if (PROXY_WORKER_IS_USABLE(worker)) {
                            return worker;
                    } else {
                        /*
                         * We have a worker that is unusable.
                         * It can be in error or disabled, but in case
                         * it has a redirection set use that redirection worker.
                         * This enables to safely remove the member from the
                         * balancer. Of course you will need some kind of
                         * session replication between those two remote.
                         */
                        if (*worker->s->redirect) {
                            proxy_worker *rworker = NULL;
                            rworker = find_route_worker(balancer, worker->s->redirect, r);
                            /* Check if the redirect worker is usable */
                            if (rworker && !PROXY_WORKER_IS_USABLE(rworker)) {
                                /*
                                 * 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.
                                 */
                                ap_proxy_retry_worker("BALANCER", rworker, r->server);
                            }
                            if (rworker && PROXY_WORKER_IS_USABLE(rworker))
                                return rworker;
                        }
                    }
                }
        worker++;
            }
        }
        checked_standby = checking_standby++;
    }
    return NULL;
}
@@ -210,42 +258,7 @@ static proxy_worker *find_session_route(proxy_balancer *balancer,
        /* We have a route in path or in cookie
         * Find the worker that has this route defined.
         */
        worker = find_route_worker(balancer, *route);
        if (worker && !PROXY_WORKER_IS_USABLE(worker)) {
            /*
             * 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.
             */
            ap_proxy_retry_worker("BALANCER", worker, r->server);
            if (!PROXY_WORKER_IS_USABLE(worker)) {
                /*
                 * We have a worker that is unusable.
                 * It can be in error or disabled, but in case
                 * it has a redirection set use that redirection worker.
                 * This enables to safely remove the member from the
                 * balancer. Of course you will need some kind of
                 * session replication between those two remote.
                 */
                if (*worker->s->redirect)
                    worker = find_route_worker(balancer, worker->s->redirect);
                /* Check if the redirect worker is usable */
                if (worker && !PROXY_WORKER_IS_USABLE(worker)) {
                    /*
                     * 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.
                     */
                    ap_proxy_retry_worker("BALANCER", worker, r->server);
                    if (!PROXY_WORKER_IS_USABLE(worker))
                        worker = NULL;
                }
            }
        }
        worker = find_route_worker(balancer, *route, r);
        return worker;
    }
    else
@@ -370,6 +383,9 @@ static int proxy_balancer_pre_request(proxy_worker **worker,
        for (i = 0; i < (*balancer)->workers->nelts; i++) {
            /* Take into calculation only the workers that are
             * not in error state or not disabled.
             *
             * TODO: Abstract the below, since this is dependent
             *       on the LB implementation
             */
            if (PROXY_WORKER_IS_USABLE(workers)) {
                workers->s->lbstatus += workers->s->lbfactor;
@@ -663,11 +679,15 @@ static int balancer_handler(request_rec *r)
                ap_rprintf(r, "</td><td>%d</td><td>", worker->s->lbfactor);
                if (worker->s->status & PROXY_WORKER_DISABLED)
                   ap_rputs("Dis ", r);
                else if (worker->s->status & PROXY_WORKER_IN_ERROR)
                if (worker->s->status & PROXY_WORKER_IN_ERROR)
                   ap_rputs("Err ", r);
                else if (worker->s->status & PROXY_WORKER_INITIALIZED)
                if (worker->s->status & PROXY_WORKER_STOPPED)
                   ap_rputs("Stop ", r);
                if (worker->s->status & PROXY_WORKER_HOT_STANDBY)
                   ap_rputs("Stby ", r);
                if (PROXY_WORKER_IS_USABLE(worker))
                    ap_rputs("Ok", r);
                else
                if (!PROXY_WORKER_IS_INITIALIZED(worker))
                    ap_rputs("-", r);
                ap_rputs("</td></tr>\n", r);

@@ -817,16 +837,21 @@ static proxy_worker *find_best_byrequests(proxy_balancer *balancer,
{
    int i;
    int total_factor = 0;
    proxy_worker *worker = (proxy_worker *)balancer->workers->elts;
    proxy_worker *worker;
    proxy_worker *mycandidate = NULL;

    int checking_standby = 0;
    int checked_standby = 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 */
    for (i = 0; i < balancer->workers->nelts; i++) {
    while (!mycandidate && !checked_standby) {
        worker = (proxy_worker *)balancer->workers->elts;
        for (i = 0; i < balancer->workers->nelts; i++, worker++) {
            if ( (checking_standby ? !PROXY_WORKER_IS_STANDBY(worker) : PROXY_WORKER_IS_STANDBY(worker)) )
                continue;
            /* If the worker is in error state run
             * retry on that worker. It will be marked as
             * operational if the retry timeout is elapsed.
@@ -844,7 +869,8 @@ static proxy_worker *find_best_byrequests(proxy_balancer *balancer,
                if (!mycandidate || worker->s->lbstatus > mycandidate->s->lbstatus)
                    mycandidate = worker;
            }
        worker++;
        }
        checked_standby = checking_standby++;
    }

    if (mycandidate) {
@@ -878,7 +904,9 @@ static proxy_worker *find_best_bytraffic(proxy_balancer *balancer,
    int i;
    apr_off_t mytraffic = 0;
    apr_off_t curmin = 0;
    proxy_worker *worker = (proxy_worker *)balancer->workers->elts;
    proxy_worker *worker;
    int checking_standby = 0;
    int checked_standby = 0;
    proxy_worker *mycandidate = NULL;

    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
@@ -886,7 +914,11 @@ static proxy_worker *find_best_bytraffic(proxy_balancer *balancer,
                 balancer->name);

    /* First try to see if we have available candidate */
    for (i = 0; i < balancer->workers->nelts; i++) {
    while (!mycandidate && !checked_standby) {
        worker = (proxy_worker *)balancer->workers->elts;
        for (i = 0; i < balancer->workers->nelts; i++, worker++) {
            if ( (checking_standby ? !PROXY_WORKER_IS_STANDBY(worker) : PROXY_WORKER_IS_STANDBY(worker)) )
                continue;
            /* If the worker is in error state run
             * retry on that worker. It will be marked as
             * operational if the retry timeout is elapsed.
@@ -906,7 +938,8 @@ static proxy_worker *find_best_bytraffic(proxy_balancer *balancer,
                    curmin = mytraffic;
                }
            }
        worker++;
        }
        checked_standby = checking_standby++;
    }

    if (mycandidate) {
Loading