mirror of
https://github.com/apache/httpd.git
synced 2025-08-08 15:02:10 +03:00
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
This commit is contained in:
4
CHANGES
4
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
|
||||
|
@@ -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);
|
||||
|
@@ -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 */
|
||||
};
|
||||
|
||||
/*
|
||||
|
@@ -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++;
|
||||
|
Reference in New Issue
Block a user