]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
Merge r420936, r420954, r420986, r421283 from trunk:
authorJim Jagielski <jim@apache.org>
Wed, 30 Aug 2006 17:50:47 +0000 (17:50 +0000)
committerJim Jagielski <jim@apache.org>
Wed, 30 Aug 2006 17:50:47 +0000 (17:50 +0000)
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

CHANGES
STATUS
modules/proxy/mod_proxy.c
modules/proxy/mod_proxy.h
modules/proxy/mod_proxy_balancer.c
modules/proxy/proxy_util.c

diff --git a/CHANGES b/CHANGES
index 8403fa60b834b9625e7024000416d9bdc3145fdd..916b9c64fa87dd74293129951a620722f62671be 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,11 @@
                                                         -*- 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>]
 
diff --git a/STATUS b/STATUS
index c6b29c2f4edfe6362e705823e1807574b3204a93..3c8a3d5ea31ba34f00f9f2e0a9589558a62e44b3 100644 (file)
--- a/STATUS
+++ b/STATUS
@@ -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.
index 09ef3a72a59cd25a1256c817fa7bf0c7d336df71..41f7c0fb9df0000536f434d61ac13efe7ba8855d 100644 (file)
@@ -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";
             }
         }
     }
index 2af400dc1588a571246230c9bd0d677f14f31189..e0fb8adc94945c3b193e2de27fee670f0a2a3c31 100644 (file)
@@ -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
index 1fb57db9d434ef3a2ed0a04c5354155bfaa1ad9a..d06dad46034e0582d89890b82a8f426dc434d74b 100644 (file)
@@ -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++) {
-        if (*(worker->s->route) && strcmp(worker->s->route, route) == 0) {
-            return worker;
+    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;
@@ -662,12 +678,16 @@ static int balancer_handler(request_rec *r)
                 ap_rvputs(r, "</td><td>", worker->s->redirect, NULL);
                 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)
-                    ap_rputs("Err", r);
-                else if (worker->s->status & PROXY_WORKER_INITIALIZED)
+                   ap_rputs("Dis ", r);
+                if (worker->s->status & PROXY_WORKER_IN_ERROR)
+                   ap_rputs("Err ", r);
+                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,34 +837,40 @@ 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++) {
-        /* 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.
-         */
-        if (!PROXY_WORKER_IS_USABLE(worker))
-            ap_proxy_retry_worker("BALANCER", worker, r->server);
-        /* Take into calculation only the workers that are
-         * not in error state or not disabled.
-         */
-        if (PROXY_WORKER_IS_USABLE(worker)) {
-            worker->s->lbstatus += worker->s->lbfactor;
-            total_factor += worker->s->lbfactor;
-            if (!mycandidate || worker->s->lbstatus > mycandidate->s->lbstatus)
-                mycandidate = worker;
+    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.
+             * The worker might still be unusable, but we try
+             * anyway.
+             */
+            if (!PROXY_WORKER_IS_USABLE(worker))
+                ap_proxy_retry_worker("BALANCER", worker, r->server);
+            /* Take into calculation only the workers that are
+             * not in error state or not disabled.
+             */
+            if (PROXY_WORKER_IS_USABLE(worker)) {
+                worker->s->lbstatus += worker->s->lbfactor;
+                total_factor += worker->s->lbfactor;
+                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,27 +914,32 @@ 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++) {
-        /* 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.
-         */
-        if (!PROXY_WORKER_IS_USABLE(worker))
-            ap_proxy_retry_worker("BALANCER", worker, r->server);
-        /* Take into calculation only the workers that are
-         * not in error state or not disabled.
-         */
-        if (PROXY_WORKER_IS_USABLE(worker)) {
-            mytraffic = (worker->s->transferred/worker->s->lbfactor) +
-                        (worker->s->read/worker->s->lbfactor);
-            if (!mycandidate || mytraffic < curmin) {
-                mycandidate = worker;
-                curmin = mytraffic;
+    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.
+             * The worker might still be unusable, but we try
+             * anyway.
+             */
+            if (!PROXY_WORKER_IS_USABLE(worker))
+                ap_proxy_retry_worker("BALANCER", worker, r->server);
+            /* Take into calculation only the workers that are
+             * not in error state or not disabled.
+             */
+            if (PROXY_WORKER_IS_USABLE(worker)) {
+                mytraffic = (worker->s->transferred/worker->s->lbfactor) +
+                            (worker->s->read/worker->s->lbfactor);
+                if (!mycandidate || mytraffic < curmin) {
+                    mycandidate = worker;
+                    curmin = mytraffic;
+                }
             }
         }
-        worker++;
+        checked_standby = checking_standby++;
     }
 
     if (mycandidate) {
index 908c704a032eed0effc1fb51efe21f1edb9e28ec..a6f9874d4bc287c355968c0d7f377a4770e0436a 100644 (file)
@@ -1605,7 +1605,7 @@ PROXY_DECLARE(void) ap_proxy_initialize_worker_share(proxy_server_conf *conf,
     void *score = NULL;
 #endif
 
-    if (worker->s && (worker->s->status & PROXY_WORKER_INITIALIZED)) {
+    if (worker->s && PROXY_WORKER_IS_INITIALIZED(worker)) {
         /* The worker share is already initialized */
         ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
               "proxy: worker %s already initialized",
@@ -1639,7 +1639,7 @@ PROXY_DECLARE(void) ap_proxy_initialize_worker_share(proxy_server_conf *conf,
      * recheck to see if we've already been here. Possible
      * if proxy is using scoreboard to hold shared stats
      */
-    if (worker->s->status & PROXY_WORKER_INITIALIZED) {
+    if (PROXY_WORKER_IS_INITIALIZED(worker)) {
         /* The worker share is already initialized */
         ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
               "proxy: worker %s already initialized",
@@ -1667,7 +1667,7 @@ PROXY_DECLARE(apr_status_t) ap_proxy_initialize_worker(proxy_worker *worker, ser
     int mpm_threads;
 #endif
 
-    if (worker->status & PROXY_WORKER_INITIALIZED) {
+    if (PROXY_WORKER_IS_INITIALIZED(worker)) {
         /* The worker is already initialized */
         return APR_SUCCESS;
     }