]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
Add in a very simple balancer "set" concept, which allows
authorJim Jagielski <jim@apache.org>
Mon, 31 Jul 2006 17:01:40 +0000 (17:01 +0000)
committerJim Jagielski <jim@apache.org>
Mon, 31 Jul 2006 17:01:40 +0000 (17:01 +0000)
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

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

diff --git a/CHANGES b/CHANGES
index 5cc374d3a7937b52f218332ffadd6421dbf6c6e5..5f5da5276f8f25ff598e26b5a7ac70fa5e8f02e7 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -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
index 2b1a9ba3d04cadf1396315ad334c2f14e21e2e69..10865704fbff226ef43661dd08a335e4eeb1d144 100644 (file)
@@ -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);
index c6f8077af8e7d3f06368e90b5a668dbf7d0849b1..413953e65b7ef1d32b86cb47d038a9f6e53930d8 100644 (file)
@@ -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 */
@@ -309,31 +311,32 @@ struct proxy_worker {
     apr_interval_time_t ttl;    /* maximum amount of time in seconds a connection
                                  * may be available while exceeding the soft limit */
     apr_interval_time_t timeout; /* connection timeout */
-    char                timeout_set;
+    char            timeout_set;
     apr_interval_time_t acquire; /* acquire timeout when the maximum number of connections is exceeded */
-    char                acquire_set;
-    apr_size_t          recv_buffer_size;
-    char                recv_buffer_size_set;
-    apr_size_t          io_buffer_size;
-    char                io_buffer_size_set;
-    char                keepalive;
-    char                keepalive_set;
+    char            acquire_set;
+    apr_size_t      recv_buffer_size;
+    char            recv_buffer_size_set;
+    apr_size_t      io_buffer_size;
+    char            io_buffer_size_set;
+    char            keepalive;
+    char            keepalive_set;
     proxy_conn_pool     *cp;        /* Connection pool to use */
     proxy_worker_stat   *s;         /* Shared data */
-    void                *opaque;    /* per scheme worker data */
-    int                 is_address_reusable;
+    void            *opaque;    /* per scheme worker data */
+    int             is_address_reusable;
 #if APR_HAS_THREADS
     apr_thread_mutex_t  *mutex;  /* Thread lock for updating address cache */
 #endif
-    void                *context;   /* general purpose storage */
+    void            *context;   /* general purpose storage */
     enum {
          flush_off,
          flush_on,
          flush_auto
     } flush_packets;           /* control AJP flushing */
-    int                 flush_wait;  /* poll wait time in microseconds if flush_auto */
+    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 */
 };
 
 /*
index ff0322f6637ae48cbf2c00edf044099e27fd5dfc..27b43cb7cfe2c5f9a6eb15f3ffeabed1e2ac465d 100644 (file)
@@ -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,37 +878,48 @@ 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 */
-    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;
+    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
+                 * 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;
+                }
             }
+            checked_standby = checking_standby++;
         }
-        checked_standby = checking_standby++;
-    }
+        cur_lbset++;
+    } while (cur_lbset < max_lbset && !mycandidate);
 
     if (mycandidate) {
         mycandidate->s->lbstatus -= total_factor;
@@ -934,39 +956,50 @@ 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 */
-    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;
+    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
+                 * 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;
+                    }
                 }
             }
+            checked_standby = checking_standby++;
         }
-        checked_standby = checking_standby++;
-    }
+        cur_lbset++;
+    } while (cur_lbset < max_lbset && !mycandidate);
 
     if (mycandidate) {
         mycandidate->s->elected++;