View | Details | Raw Unified | Return to bug 61140
Collapse All | Expand All

(-)a/docs/log-message-tags/next-number (-1 / +1 lines)
Line 1 Link Here
1
10033
1
10034
(-)a/docs/manual/howto/reverse_proxy.xml (-26 / +51 lines)
Lines 147-153 Link Here
147
147
148
    <note type="hint"><title>Hint</title>
148
    <note type="hint"><title>Hint</title>
149
      <p>
149
      <p>
150
      	<em>BalancerMembers</em> are also sometimes referred to as <em>workers</em>.
150
        <em>BalancerMembers</em> are also sometimes referred to as <em>workers</em>.
151
      </p>
151
      </p>
152
   </note>
152
   </note>
153
153
Lines 182-201 Link Here
182
    <title>Failover</title>
182
    <title>Failover</title>
183
183
184
    <p>
184
    <p>
185
      You can also fine-tune various failover scenarios, detailing which
185
      You can also fine-tune various failover scenarios, detailing which workers
186
      workers and even which balancers should accessed in such cases. For
186
      and even which balancers should accessed in such cases. For example, the
187
      example, the below setup implements 2 failover cases: In the first,
187
      below setup implements three failover cases:
188
      <code>http://hstandby.example.com:8080</code> is only sent traffic
188
    </p>
189
      if all other workers in the <em>myset</em> balancer are not available.
189
    <ol>
190
      If that worker itself is not available, only then will the
190
      <li>
191
      <code>http://bkup1.example.com:8080</code> and <code>http://bkup2.example.com:8080</code>
191
        <code>http://spare1.example.com:8080</code> and
192
      workers be brought into rotation:
192
        <code>http://spare2.example.com:8080</code> are only sent traffic if one
193
        or both of <code>http://www2.example.com:8080</code> or
194
        <code>http://www3.example.com:8080</code> is unavailable. (One spare
195
        will be used to replace one unusable member of the same balancer set.)
196
      </li>
197
      <li>
198
        <code>http://hstandby.example.com:8080</code> is only sent traffic if
199
        all other workers in balancer set <code>0</code> are not available.
200
      </li>
201
      <li>
202
        If all load balancer set <code>0</code> workers, spares, and the standby
203
        are unavailable, only then will the
204
        <code>http://bkup1.example.com:8080</code> and
205
        <code>http://bkup2.example.com:8080</code> workers from balancer set
206
        <code>1</code> be brought into rotation.
207
      </li>
208
    </ol>
209
    <p>
210
      Thus, it is possible to have one or more hot spares and hot standbys for
211
      each load balancer set.
193
    </p>
212
    </p>
194
213
195
    <highlight language="config">
214
    <highlight language="config">
196
&lt;Proxy balancer://myset&gt;
215
&lt;Proxy balancer://myset&gt;
197
    BalancerMember http://www2.example.com:8080
216
    BalancerMember http://www2.example.com:8080
198
    BalancerMember http://www3.example.com:8080 loadfactor=3 timeout=1
217
    BalancerMember http://www3.example.com:8080 loadfactor=3 timeout=1
218
    BalancerMember http://spare1.example.com:8080 status=+R
219
    BalancerMember http://spare2.example.com:8080 status=+R
199
    BalancerMember http://hstandby.example.com:8080 status=+H
220
    BalancerMember http://hstandby.example.com:8080 status=+H
200
    BalancerMember http://bkup1.example.com:8080 lbset=1
221
    BalancerMember http://bkup1.example.com:8080 lbset=1
201
    BalancerMember http://bkup2.example.com:8080 lbset=1
222
    BalancerMember http://bkup2.example.com:8080 lbset=1
Lines 207-217 Link Here
207
    </highlight>
228
    </highlight>
208
229
209
    <p>
230
    <p>
210
      The magic of this failover setup is setting <code>http://hstandby.example.com:8080</code>
231
      For failover, hot spares are used as replacements for failed or unusable
211
      with the <code>+H</code> status flag, which puts it in <em>hot standby</em> mode,
232
      workers in the same load balancer set. Hot standbys are used if all
212
      and making the 2 <code>bkup#</code> servers part of the #1 load balancer set (the
233
      workers and spares in the load balancer set are unavailable. Load balancer
213
      default set is 0); for failover, hot standbys (if they exist) are used 1st, when all regular
234
      sets (with their respective hot spares and standbys) are always tried in
214
      workers are unavailable; load balancer sets with lowest number are always tried first.
235
      order from lowest to highest.
215
    </p>
236
    </p>
216
237
217
  </section>
238
  </section>
Lines 221-234 Link Here
221
242
222
    <p>
243
    <p>
223
      One of the most unique and useful features of Apache httpd's reverse proxy is
244
      One of the most unique and useful features of Apache httpd's reverse proxy is
224
	  the embedded <em>balancer-manager</em> application. Similar to
245
          the embedded <em>balancer-manager</em> application. Similar to
225
	  <module>mod_status</module>, <em>balancer-manager</em> displays
246
          <module>mod_status</module>, <em>balancer-manager</em> displays
226
	  the current working configuration and status of the enabled
247
          the current working configuration and status of the enabled
227
	  balancers and workers currently in use. However, not only does it
248
          balancers and workers currently in use. However, not only does it
228
	  display these parameters, it also allows for dynamic, runtime, on-the-fly
249
          display these parameters, it also allows for dynamic, runtime, on-the-fly
229
	  reconfiguration of almost all of them, including adding new <em>BalancerMembers</em>
250
          reconfiguration of almost all of them, including adding new <em>BalancerMembers</em>
230
	  (workers) to an existing balancer. To enable these capability, the following
251
          (workers) to an existing balancer. To enable these capability, the following
231
	  needs to be added to your configuration:
252
          needs to be added to your configuration:
232
    </p>
253
    </p>
233
254
234
    <highlight language="config">
255
    <highlight language="config">
Lines 293-308 Link Here
293
      is displayed and can be set/reset. The meanings of these statuses are as follows:
314
      is displayed and can be set/reset. The meanings of these statuses are as follows:
294
    </p>
315
    </p>
295
      <table border="1">
316
      <table border="1">
296
      	<tr><th>Flag</th><th>String</th><th>Description</th></tr>
317
        <tr><th>Flag</th><th>String</th><th>Description</th></tr>
297
      	<tr><td>&nbsp;</td><td><em>Ok</em></td><td>Worker is available</td></tr>
318
        <tr><td>&nbsp;</td><td><em>Ok</em></td><td>Worker is available</td></tr>
298
      	<tr><td>&nbsp;</td><td><em>Init</em></td><td>Worker has been initialized</td></tr>
319
        <tr><td>&nbsp;</td><td><em>Init</em></td><td>Worker has been initialized</td></tr>
299
        <tr><td><code>D</code></td><td><em>Dis</em></td><td>Worker is disabled and will not accept any requests; will be
320
        <tr><td><code>D</code></td><td><em>Dis</em></td><td>Worker is disabled and will not accept any requests; will be
300
                    automatically retried.</td></tr>
321
                    automatically retried.</td></tr>
301
        <tr><td><code>S</code></td><td><em>Stop</em></td><td>Worker is administratively stopped; will not accept requests
322
        <tr><td><code>S</code></td><td><em>Stop</em></td><td>Worker is administratively stopped; will not accept requests
302
                    and will not be automatically retried</td></tr>
323
                    and will not be automatically retried</td></tr>
303
        <tr><td><code>I</code></td><td><em>Ign</em></td><td>Worker is in ignore-errors mode and will always be considered available.</td></tr>
324
        <tr><td><code>I</code></td><td><em>Ign</em></td><td>Worker is in ignore-errors mode and will always be considered available.</td></tr>
325
        <tr><td><code>R</code></td><td><em>Spar</em></td><td>Worker is a hot spare. For each worker in a given lbset that is unusable
326
                    (disabled, stopped, in error, etc.), a usable hot spare with the same lbset will be used in
327
                    its place. Hot spares can help ensure that a specific number of workers are always available
328
                    for use by a balancer.</td></tr>
304
        <tr><td><code>H</code></td><td><em>Stby</em></td><td>Worker is in hot-standby mode and will only be used if no other
329
        <tr><td><code>H</code></td><td><em>Stby</em></td><td>Worker is in hot-standby mode and will only be used if no other
305
                    viable workers are available.</td></tr>
330
                    viable workers or spares are available in the balancer set.</td></tr>
306
        <tr><td><code>E</code></td><td><em>Err</em></td><td>Worker is in an error state, usually due to failing pre-request check;
331
        <tr><td><code>E</code></td><td><em>Err</em></td><td>Worker is in an error state, usually due to failing pre-request check;
307
                    requests will not be proxied to this worker, but it will be retried depending on
332
                    requests will not be proxied to this worker, but it will be retried depending on
308
                    the <code>retry</code> setting of the worker.</td></tr>
333
                    the <code>retry</code> setting of the worker.</td></tr>
(-)a/docs/manual/mod/mod_proxy.xml (-9 / +29 lines)
Lines 306-315 Link Here
306
      <note><title>DNS resolution for origin domains</title>
306
      <note><title>DNS resolution for origin domains</title>
307
      <p>DNS resolution happens when the socket to
307
      <p>DNS resolution happens when the socket to
308
        the origin domain is created for the first time.
308
        the origin domain is created for the first time.
309
        When connection pooling is used, each backend domain is resolved 
309
        When connection pooling is used, each backend domain is resolved
310
        only once per child process, and reused for all further connections 
310
        only once per child process, and reused for all further connections
311
        until the child is recycled. This information should to be considered 
311
        until the child is recycled. This information should to be considered
312
        while planning DNS maintenance tasks involving backend domains. 
312
        while planning DNS maintenance tasks involving backend domains.
313
        Please also check <directive module="mod_proxy">ProxyPass</directive>
313
        Please also check <directive module="mod_proxy">ProxyPass</directive>
314
        parameters for more details about connection reuse.
314
        parameters for more details about connection reuse.
315
        </p>
315
        </p>
Lines 398-404 Link Here
398
&lt;/Location&gt;
398
&lt;/Location&gt;
399
        </highlight>
399
        </highlight>
400
400
401
      <p> In 2.4.26 and later, the "no-proxy" environment variable can be set to disable 
401
      <p> In 2.4.26 and later, the "no-proxy" environment variable can be set to disable
402
      <module>mod_proxy</module> processing the current request.
402
      <module>mod_proxy</module> processing the current request.
403
      This variable should be set with <directive module="mod_setenvif"
403
      This variable should be set with <directive module="mod_setenvif"
404
      >SetEnvIf</directive>, as <directive module="mod_env">SetEnv</directive>
404
      >SetEnvIf</directive>, as <directive module="mod_env">SetEnv</directive>
Lines 983-989 Link Here
983
      general <directive>ProxyPass</directive> directives. In 2.4.26 and later, the "no-proxy"
983
      general <directive>ProxyPass</directive> directives. In 2.4.26 and later, the "no-proxy"
984
      environment variable is an alternative to exclusions, and is the only
984
      environment variable is an alternative to exclusions, and is the only
985
      way to configure an exclusion of a <directive>ProxyPass</directive>
985
      way to configure an exclusion of a <directive>ProxyPass</directive>
986
      directive in <directive module="core">Location</directive> context. 
986
      directive in <directive module="core">Location</directive> context.
987
      This variable should be set with <directive module="mod_setenvif"
987
      This variable should be set with <directive module="mod_setenvif"
988
      >SetEnvIf</directive>, as <directive module="mod_env">SetEnv</directive>
988
      >SetEnvIf</directive>, as <directive module="mod_env">SetEnv</directive>
989
      is not evaluated early enough.
989
      is not evaluated early enough.
Lines 1180-1187 Link Here
1180
         <tr><td><code>S</code></td><td>Worker is administratively stopped; will not accept requests
1180
         <tr><td><code>S</code></td><td>Worker is administratively stopped; will not accept requests
1181
                    and will not be automatically retried</td></tr>
1181
                    and will not be automatically retried</td></tr>
1182
         <tr><td><code>I</code></td><td>Worker is in ignore-errors mode and will always be considered available.</td></tr>
1182
         <tr><td><code>I</code></td><td>Worker is in ignore-errors mode and will always be considered available.</td></tr>
1183
         <tr><td><code>R</code></td><td>Worker is a hot spare. For each worker in a given lbset that is unusable
1184
                    (disabled, stopped, in error, etc.), a usable hot spare with the same lbset will be used in
1185
                    its place. Hot spares can help ensure that a specific number of workers are always available
1186
                    for use by a balancer.</td></tr>
1183
         <tr><td><code>H</code></td><td>Worker is in hot-standby mode and will only be used if no other
1187
         <tr><td><code>H</code></td><td>Worker is in hot-standby mode and will only be used if no other
1184
                    viable workers are available.</td></tr>
1188
                    viable workers or spares are available in the balancer set.</td></tr>
1185
         <tr><td><code>E</code></td><td>Worker is in an error state.</td></tr>
1189
         <tr><td><code>E</code></td><td>Worker is in an error state.</td></tr>
1186
         <tr><td><code>N</code></td><td>Worker is in drain mode and will only accept existing sticky sessions
1190
         <tr><td><code>N</code></td><td>Worker is in drain mode and will only accept existing sticky sessions
1187
                    destined for itself and ignore all other requests.</td></tr>
1191
                    destined for itself and ignore all other requests.</td></tr>
Lines 1335-1342 Link Here
1335
&lt;/Proxy&gt;
1339
&lt;/Proxy&gt;
1336
    </highlight>
1340
    </highlight>
1337
1341
1342
    <p>Configuring hot spares can help ensure that a certain number of
1343
    workers are always available for use per load balancer set:</p>
1344
    <highlight language="config">
1345
ProxyPass "/" "balancer://sparecluster/"
1346
&lt;Proxy balancer://sparecluster&gt;
1347
    BalancerMember ajp://1.2.3.4:8009
1348
    BalancerMember ajp://1.2.3.5:8009
1349
    # The servers below are hot spares. For each server above that is unusable
1350
    # (disabled, stopped, unreachable, in error state, etc.), one of these spares
1351
    # will be used in its place. Two servers will always be available for a request
1352
    # unless one or more of the spares is also unusable.
1353
    BalancerMember ajp://1.2.3.6:8009 status=+R
1354
    BalancerMember ajp://1.2.3.7:8009 status=+R
1355
&lt;/Proxy&gt;
1356
    </highlight>
1357
1338
    <p>Setting up a hot-standby that will only be used if no other
1358
    <p>Setting up a hot-standby that will only be used if no other
1339
     members are available:</p>
1359
    members (or spares) are available in the load balancer set:</p>
1340
    <highlight language="config">
1360
    <highlight language="config">
1341
ProxyPass "/" "balancer://hotcluster/"
1361
ProxyPass "/" "balancer://hotcluster/"
1342
&lt;Proxy balancer://hotcluster&gt;
1362
&lt;Proxy balancer://hotcluster&gt;
Lines 1393-1399 Link Here
1393
<name>ProxyPassMatch</name>
1413
<name>ProxyPassMatch</name>
1394
<description>Maps remote servers into the local server URL-space using regular expressions</description>
1414
<description>Maps remote servers into the local server URL-space using regular expressions</description>
1395
<syntax>ProxyPassMatch [<var>regex</var>] !|<var>url</var> [<var>key=value</var>
1415
<syntax>ProxyPassMatch [<var>regex</var>] !|<var>url</var> [<var>key=value</var>
1396
	<var>[key=value</var> ...]]</syntax>
1416
        <var>[key=value</var> ...]]</syntax>
1397
<contextlist><context>server config</context><context>virtual host</context>
1417
<contextlist><context>server config</context><context>virtual host</context>
1398
<context>directory</context>
1418
<context>directory</context>
1399
</contextlist>
1419
</contextlist>
(-)a/modules/proxy/balancers/mod_lbmethod_bybusyness.c (-58 / +22 lines)
Lines 26-42 Link Here
26
        proxy_worker *worker, server_rec *s) = NULL;
26
        proxy_worker *worker, server_rec *s) = NULL;
27
27
28
static proxy_worker *find_best_bybusyness(proxy_balancer *balancer,
28
static proxy_worker *find_best_bybusyness(proxy_balancer *balancer,
29
                                request_rec *r)
29
                                          request_rec *r)
30
{
30
{
31
    int i;
31
    int i;
32
    int total_factor = 0;
33
    apr_array_header_t *workers;
32
    proxy_worker **worker;
34
    proxy_worker **worker;
33
    proxy_worker *mycandidate = NULL;
35
    proxy_worker *mycandidate = NULL;
34
    int cur_lbset = 0;
36
    apr_pool_t *wpool;
35
    int max_lbset = 0;
36
    int checking_standby;
37
    int checked_standby;
38
39
    int total_factor = 0;
40
37
41
    if (!ap_proxy_retry_worker_fn) {
38
    if (!ap_proxy_retry_worker_fn) {
42
        ap_proxy_retry_worker_fn =
39
        ap_proxy_retry_worker_fn =
Lines 51-117 Link Here
51
                 "proxy: Entering bybusyness for BALANCER (%s)",
48
                 "proxy: Entering bybusyness for BALANCER (%s)",
52
                 balancer->s->name);
49
                 balancer->s->name);
53
50
54
    /* First try to see if we have available candidate */
51
    apr_pool_create(&wpool, r->pool);
55
    do {
56
57
        checking_standby = checked_standby = 0;
58
        while (!mycandidate && !checked_standby) {
59
60
            worker = (proxy_worker **)balancer->workers->elts;
61
            for (i = 0; i < balancer->workers->nelts; i++, worker++) {
62
                if  (!checking_standby) {    /* first time through */
63
                    if ((*worker)->s->lbset > max_lbset)
64
                        max_lbset = (*worker)->s->lbset;
65
                }
66
                if (
67
                    ((*worker)->s->lbset != cur_lbset) ||
68
                    (checking_standby ? !PROXY_WORKER_IS_STANDBY(*worker) : PROXY_WORKER_IS_STANDBY(*worker)) ||
69
                    (PROXY_WORKER_IS_DRAINING(*worker))
70
                    ) {
71
                    continue;
72
                }
73
52
74
                /* If the worker is in error state run
53
    workers = ap_proxy_balancer_usable_workers(balancer, r, wpool);
75
                 * retry on that worker. It will be marked as
76
                 * operational if the retry timeout is elapsed.
77
                 * The worker might still be unusable, but we try
78
                 * anyway.
79
                 */
80
                if (!PROXY_WORKER_IS_USABLE(*worker)) {
81
                    ap_proxy_retry_worker_fn("BALANCER", *worker, r->server);
82
                }
83
84
                /* Take into calculation only the workers that are
85
                 * not in error state or not disabled.
86
                 */
87
                if (PROXY_WORKER_IS_USABLE(*worker)) {
88
54
89
                    (*worker)->s->lbstatus += (*worker)->s->lbfactor;
55
    for (i = 0; i < workers->nelts; i++) {
90
                    total_factor += (*worker)->s->lbfactor;
56
        worker = &APR_ARRAY_IDX(workers, i, proxy_worker *);
91
57
        (*worker)->s->lbstatus += (*worker)->s->lbfactor;
92
                    if (!mycandidate
58
        total_factor += (*worker)->s->lbfactor;
93
                        || (*worker)->s->busy < mycandidate->s->busy
94
                        || ((*worker)->s->busy == mycandidate->s->busy && (*worker)->s->lbstatus > mycandidate->s->lbstatus))
95
                        mycandidate = *worker;
96
59
97
                }
60
        if (
98
61
            !mycandidate
99
            }
62
            || ((*worker)->s->busy < mycandidate->s->busy)
63
            || (
64
                ((*worker)->s->busy == mycandidate->s->busy)
65
                && ((*worker)->s->lbstatus > mycandidate->s->lbstatus)
66
            )
67
        ) {
68
            mycandidate = *worker;
69
        }
70
    }
100
71
101
            checked_standby = checking_standby++;
72
    apr_pool_destroy(wpool);
102
103
        }
104
105
        cur_lbset++;
106
107
    } while (cur_lbset <= max_lbset && !mycandidate);
108
73
109
    if (mycandidate) {
74
    if (mycandidate) {
110
        mycandidate->s->lbstatus -= total_factor;
75
        mycandidate->s->lbstatus -= total_factor;
111
        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, APLOGNO(01212)
76
        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, APLOGNO(01212)
112
                     "proxy: bybusyness selected worker \"%s\" : busy %" APR_SIZE_T_FMT " : lbstatus %d",
77
                     "proxy: bybusyness selected worker \"%s\" : busy %" APR_SIZE_T_FMT " : lbstatus %d",
113
                     mycandidate->s->name, mycandidate->s->busy, mycandidate->s->lbstatus);
78
                     mycandidate->s->name, mycandidate->s->busy, mycandidate->s->lbstatus);
114
115
    }
79
    }
116
80
117
    return mycandidate;
81
    return mycandidate;
(-)a/modules/proxy/balancers/mod_lbmethod_byrequests.c (-44 / +19 lines)
Lines 72-87 Link Here
72
 */
72
 */
73
73
74
static proxy_worker *find_best_byrequests(proxy_balancer *balancer,
74
static proxy_worker *find_best_byrequests(proxy_balancer *balancer,
75
                                request_rec *r)
75
                                          request_rec *r)
76
{
76
{
77
    int i;
77
    int i;
78
    int total_factor = 0;
78
    int total_factor = 0;
79
    apr_array_header_t *workers;
79
    proxy_worker **worker;
80
    proxy_worker **worker;
80
    proxy_worker *mycandidate = NULL;
81
    proxy_worker *mycandidate = NULL;
81
    int cur_lbset = 0;
82
    apr_pool_t *wpool;
82
    int max_lbset = 0;
83
    int checking_standby;
84
    int checked_standby;
85
83
86
    if (!ap_proxy_retry_worker_fn) {
84
    if (!ap_proxy_retry_worker_fn) {
87
        ap_proxy_retry_worker_fn =
85
        ap_proxy_retry_worker_fn =
Lines 96-148 Link Here
96
                 "proxy: Entering byrequests for BALANCER (%s)",
94
                 "proxy: Entering byrequests for BALANCER (%s)",
97
                 balancer->s->name);
95
                 balancer->s->name);
98
96
99
    /* First try to see if we have available candidate */
97
    apr_pool_create(&wpool, r->pool);
100
    do {
101
        checking_standby = checked_standby = 0;
102
        while (!mycandidate && !checked_standby) {
103
            worker = (proxy_worker **)balancer->workers->elts;
104
            for (i = 0; i < balancer->workers->nelts; i++, worker++) {
105
                if (!checking_standby) {    /* first time through */
106
                    if ((*worker)->s->lbset > max_lbset)
107
                        max_lbset = (*worker)->s->lbset;
108
                }
109
                if (
110
                    ((*worker)->s->lbset != cur_lbset) ||
111
                    (checking_standby ? !PROXY_WORKER_IS_STANDBY(*worker) : PROXY_WORKER_IS_STANDBY(*worker)) ||
112
                    (PROXY_WORKER_IS_DRAINING(*worker))
113
                    ) {
114
                    continue;
115
                }
116
98
117
                /* If the worker is in error state run
99
    workers = ap_proxy_balancer_usable_workers(balancer, r, wpool);
118
                 * retry on that worker. It will be marked as
100
119
                 * operational if the retry timeout is elapsed.
101
    for (i = 0; i < workers->nelts; i++) {
120
                 * The worker might still be unusable, but we try
102
        worker = &APR_ARRAY_IDX(workers, i, proxy_worker *);
121
                 * anyway.
103
        (*worker)->s->lbstatus += (*worker)->s->lbfactor;
122
                 */
104
        total_factor += (*worker)->s->lbfactor;
123
                if (!PROXY_WORKER_IS_USABLE(*worker))
105
124
                    ap_proxy_retry_worker_fn("BALANCER", *worker, r->server);
106
        if (
125
                /* Take into calculation only the workers that are
107
            !mycandidate
126
                 * not in error state or not disabled.
108
            || ((*worker)->s->lbstatus > mycandidate->s->lbstatus)
127
                 */
109
        ) {
128
                if (PROXY_WORKER_IS_USABLE(*worker)) {
110
            mycandidate = *worker;
129
                    (*worker)->s->lbstatus += (*worker)->s->lbfactor;
130
                    total_factor += (*worker)->s->lbfactor;
131
                    if (!mycandidate || (*worker)->s->lbstatus > mycandidate->s->lbstatus)
132
                        mycandidate = *worker;
133
                }
134
            }
135
            checked_standby = checking_standby++;
136
        }
111
        }
137
        cur_lbset++;
112
    }
138
    } while (cur_lbset <= max_lbset && !mycandidate);
113
114
    apr_pool_destroy(wpool);
139
115
140
    if (mycandidate) {
116
    if (mycandidate) {
141
        mycandidate->s->lbstatus -= total_factor;
117
        mycandidate->s->lbstatus -= total_factor;
142
        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, APLOGNO(01208)
118
        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, APLOGNO(01208)
143
                     "proxy: byrequests selected worker \"%s\" : busy %" APR_SIZE_T_FMT " : lbstatus %d",
119
                     "proxy: byrequests selected worker \"%s\" : busy %" APR_SIZE_T_FMT " : lbstatus %d",
144
                     mycandidate->s->name, mycandidate->s->busy, mycandidate->s->lbstatus);
120
                     mycandidate->s->name, mycandidate->s->busy, mycandidate->s->lbstatus);
145
146
    }
121
    }
147
122
148
    return mycandidate;
123
    return mycandidate;
(-)a/modules/proxy/balancers/mod_lbmethod_bytraffic.c (-44 / +16 lines)
Lines 48-59 Link Here
48
    int i;
48
    int i;
49
    apr_off_t mytraffic = 0;
49
    apr_off_t mytraffic = 0;
50
    apr_off_t curmin = 0;
50
    apr_off_t curmin = 0;
51
    apr_array_header_t *workers;
51
    proxy_worker **worker;
52
    proxy_worker **worker;
52
    proxy_worker *mycandidate = NULL;
53
    proxy_worker *mycandidate = NULL;
53
    int cur_lbset = 0;
54
    apr_pool_t *wpool;
54
    int max_lbset = 0;
55
    int checking_standby;
56
    int checked_standby;
57
55
58
    if (!ap_proxy_retry_worker_fn) {
56
    if (!ap_proxy_retry_worker_fn) {
59
        ap_proxy_retry_worker_fn =
57
        ap_proxy_retry_worker_fn =
Lines 68-115 Link Here
68
                 "proxy: Entering bytraffic for BALANCER (%s)",
66
                 "proxy: Entering bytraffic for BALANCER (%s)",
69
                 balancer->s->name);
67
                 balancer->s->name);
70
68
71
    /* First try to see if we have available candidate */
69
    apr_pool_create(&wpool, r->pool);
72
    do {
73
        checking_standby = checked_standby = 0;
74
        while (!mycandidate && !checked_standby) {
75
            worker = (proxy_worker **)balancer->workers->elts;
76
            for (i = 0; i < balancer->workers->nelts; i++, worker++) {
77
                if (!checking_standby) {    /* first time through */
78
                    if ((*worker)->s->lbset > max_lbset)
79
                        max_lbset = (*worker)->s->lbset;
80
                }
81
                if (
82
                    ((*worker)->s->lbset != cur_lbset) ||
83
                    (checking_standby ? !PROXY_WORKER_IS_STANDBY(*worker) : PROXY_WORKER_IS_STANDBY(*worker)) ||
84
                    (PROXY_WORKER_IS_DRAINING(*worker))
85
                    ) {
86
                    continue;
87
                }
88
70
89
                /* If the worker is in error state run
71
    workers = ap_proxy_balancer_usable_workers(balancer, r, wpool);
90
                 * retry on that worker. It will be marked as
72
91
                 * operational if the retry timeout is elapsed.
73
    for (i = 0; i < workers->nelts; i++) {
92
                 * The worker might still be unusable, but we try
74
        worker = &APR_ARRAY_IDX(workers, i, proxy_worker *);
93
                 * anyway.
75
        mytraffic = (*worker)->s->transferred/(*worker)->s->lbfactor
94
                 */
76
                    + (*worker)->s->read/(*worker)->s->lbfactor;
95
                if (!PROXY_WORKER_IS_USABLE(*worker))
77
96
                    ap_proxy_retry_worker_fn("BALANCER", *worker, r->server);
78
        if (!mycandidate || (mytraffic < curmin)) {
97
                /* Take into calculation only the workers that are
79
            mycandidate = *worker;
98
                 * not in error state or not disabled.
80
            curmin = mytraffic;
99
                 */
100
                if (PROXY_WORKER_IS_USABLE(*worker)) {
101
                    mytraffic = ((*worker)->s->transferred/(*worker)->s->lbfactor) +
102
                                ((*worker)->s->read/(*worker)->s->lbfactor);
103
                    if (!mycandidate || mytraffic < curmin) {
104
                        mycandidate = *worker;
105
                        curmin = mytraffic;
106
                    }
107
                }
108
            }
109
            checked_standby = checking_standby++;
110
        }
81
        }
111
        cur_lbset++;
82
    }
112
    } while (cur_lbset <= max_lbset && !mycandidate);
83
84
    apr_pool_destroy(wpool);
113
85
114
    if (mycandidate) {
86
    if (mycandidate) {
115
        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, APLOGNO(01210)
87
        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, APLOGNO(01210)
(-)a/modules/proxy/mod_proxy.c (-5 / +5 lines)
Lines 68-73 Link Here
68
    {PROXY_WORKER_STOPPED,       PROXY_WORKER_STOPPED_FLAG,       "Stop "},
68
    {PROXY_WORKER_STOPPED,       PROXY_WORKER_STOPPED_FLAG,       "Stop "},
69
    {PROXY_WORKER_IN_ERROR,      PROXY_WORKER_IN_ERROR_FLAG,      "Err "},
69
    {PROXY_WORKER_IN_ERROR,      PROXY_WORKER_IN_ERROR_FLAG,      "Err "},
70
    {PROXY_WORKER_HOT_STANDBY,   PROXY_WORKER_HOT_STANDBY_FLAG,   "Stby "},
70
    {PROXY_WORKER_HOT_STANDBY,   PROXY_WORKER_HOT_STANDBY_FLAG,   "Stby "},
71
    {PROXY_WORKER_HOT_SPARE,     PROXY_WORKER_HOT_SPARE_FLAG,     "Spar "},
71
    {PROXY_WORKER_FREE,          PROXY_WORKER_FREE_FLAG,          "Free "},
72
    {PROXY_WORKER_FREE,          PROXY_WORKER_FREE_FLAG,          "Free "},
72
    {PROXY_WORKER_HC_FAIL,       PROXY_WORKER_HC_FAIL_FLAG,       "HcFl "},
73
    {PROXY_WORKER_HC_FAIL,       PROXY_WORKER_HC_FAIL_FLAG,       "HcFl "},
73
    {0x0, '\0', NULL}
74
    {0x0, '\0', NULL}
Lines 365-371 Link Here
365
        if (strlen(val) != 1) {
366
        if (strlen(val) != 1) {
366
            if (!strcasecmp(val, "off"))
367
            if (!strcasecmp(val, "off"))
367
                balancer->s->sticky_separator = 0;
368
                balancer->s->sticky_separator = 0;
368
            else      
369
            else
369
                return "stickysessionsep must be a single character or Off";
370
                return "stickysessionsep must be a single character or Off";
370
        }
371
        }
371
        else
372
        else
Lines 787-794 Link Here
787
        || !r->uri || r->uri[0] != '/') {
788
        || !r->uri || r->uri[0] != '/') {
788
        return DECLINED;
789
        return DECLINED;
789
    }
790
    }
790
   
791
791
    if (apr_table_get(r->subprocess_env, "no-proxy")) { 
792
    if (apr_table_get(r->subprocess_env, "no-proxy")) {
792
        return DECLINED;
793
        return DECLINED;
793
    }
794
    }
794
795
Lines 1292-1298 Link Here
1292
1293
1293
    if (DECLINED == access_status) {
1294
    if (DECLINED == access_status) {
1294
        ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(01144)
1295
        ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(01144)
1295
                      "No protocol handler was valid for the URL %s " 
1296
                      "No protocol handler was valid for the URL %s "
1296
                      "(scheme '%s'). "
1297
                      "(scheme '%s'). "
1297
                      "If you are using a DSO version of mod_proxy, make sure "
1298
                      "If you are using a DSO version of mod_proxy, make sure "
1298
                      "the proxy submodules are included in the configuration "
1299
                      "the proxy submodules are included in the configuration "
Lines 3114-3117 Link Here
3114
APR_IMPLEMENT_OPTIONAL_HOOK_RUN_ALL(proxy, PROXY, int, detach_backend,
3115
APR_IMPLEMENT_OPTIONAL_HOOK_RUN_ALL(proxy, PROXY, int, detach_backend,
3115
                                    (request_rec *r, proxy_conn_rec *backend),
3116
                                    (request_rec *r, proxy_conn_rec *backend),
3116
                                    (r, backend), OK, DECLINED)
3117
                                    (r, backend), OK, DECLINED)
3117
(-)a/modules/proxy/mod_proxy.h (-2 / +17 lines)
Lines 306-311 Link Here
306
#define PROXY_WORKER_HOT_STANDBY    0x0100
306
#define PROXY_WORKER_HOT_STANDBY    0x0100
307
#define PROXY_WORKER_FREE           0x0200
307
#define PROXY_WORKER_FREE           0x0200
308
#define PROXY_WORKER_HC_FAIL        0x0400
308
#define PROXY_WORKER_HC_FAIL        0x0400
309
#define PROXY_WORKER_HOT_SPARE      0x0800
309
310
310
/* worker status flags */
311
/* worker status flags */
311
#define PROXY_WORKER_INITIALIZED_FLAG    'O'
312
#define PROXY_WORKER_INITIALIZED_FLAG    'O'
Lines 319-324 Link Here
319
#define PROXY_WORKER_HOT_STANDBY_FLAG    'H'
320
#define PROXY_WORKER_HOT_STANDBY_FLAG    'H'
320
#define PROXY_WORKER_FREE_FLAG           'F'
321
#define PROXY_WORKER_FREE_FLAG           'F'
321
#define PROXY_WORKER_HC_FAIL_FLAG        'C'
322
#define PROXY_WORKER_HC_FAIL_FLAG        'C'
323
#define PROXY_WORKER_HOT_SPARE_FLAG      'R'
322
324
323
#define PROXY_WORKER_NOT_USABLE_BITMAP ( PROXY_WORKER_IN_SHUTDOWN | \
325
#define PROXY_WORKER_NOT_USABLE_BITMAP ( PROXY_WORKER_IN_SHUTDOWN | \
324
PROXY_WORKER_DISABLED | PROXY_WORKER_STOPPED | PROXY_WORKER_IN_ERROR | \
326
PROXY_WORKER_DISABLED | PROXY_WORKER_STOPPED | PROXY_WORKER_IN_ERROR | \
Lines 329-334 Link Here
329
331
330
#define PROXY_WORKER_IS_STANDBY(f)   ( (f)->s->status &  PROXY_WORKER_HOT_STANDBY )
332
#define PROXY_WORKER_IS_STANDBY(f)   ( (f)->s->status &  PROXY_WORKER_HOT_STANDBY )
331
333
334
#define PROXY_WORKER_IS_SPARE(f)   ( (f)->s->status &  PROXY_WORKER_HOT_SPARE )
335
332
#define PROXY_WORKER_IS_USABLE(f)   ( ( !( (f)->s->status & PROXY_WORKER_NOT_USABLE_BITMAP) ) && \
336
#define PROXY_WORKER_IS_USABLE(f)   ( ( !( (f)->s->status & PROXY_WORKER_NOT_USABLE_BITMAP) ) && \
333
  PROXY_WORKER_IS_INITIALIZED(f) )
337
  PROXY_WORKER_IS_INITIALIZED(f) )
334
338
Lines 503-509 Link Here
503
    char      sticky_separator;                                /* separator for sessionid/route */
507
    char      sticky_separator;                                /* separator for sessionid/route */
504
    unsigned int    forcerecovery_set:1;
508
    unsigned int    forcerecovery_set:1;
505
    unsigned int    scolonsep_set:1;
509
    unsigned int    scolonsep_set:1;
506
    unsigned int    sticky_force_set:1; 
510
    unsigned int    sticky_force_set:1;
507
    unsigned int    nonce_set:1;
511
    unsigned int    nonce_set:1;
508
    unsigned int    sticky_separator_set:1;
512
    unsigned int    sticky_separator_set:1;
509
} proxy_balancer_shared;
513
} proxy_balancer_shared;
Lines 665-671 Link Here
665
 * @param addr      resolved address of hostname, or NULL if not known
669
 * @param addr      resolved address of hostname, or NULL if not known
666
 * @return OK on success, or else an errro
670
 * @return OK on success, or else an errro
667
 */
671
 */
668
PROXY_DECLARE(int) ap_proxy_checkproxyblock(request_rec *r, proxy_server_conf *conf, 
672
PROXY_DECLARE(int) ap_proxy_checkproxyblock(request_rec *r, proxy_server_conf *conf,
669
                                            const char *hostname, apr_sockaddr_t *addr);
673
                                            const char *hostname, apr_sockaddr_t *addr);
670
674
671
675
Lines 857-862 Link Here
857
                                                         apr_pool_t *p);
861
                                                         apr_pool_t *p);
858
862
859
/**
863
/**
864
 * Retrieve a list of usable workers for the balancer
865
 * @param balancer balancer for which usable workers should be retrieved
866
 * @param r        current request record
867
 * @param p        memory pool used for array
868
 * @return         APR array of usable workers
869
 */
870
PROXY_DECLARE(apr_array_header_t *) ap_proxy_balancer_usable_workers(proxy_balancer *balancer,
871
                                                                     request_rec *r,
872
                                                                     apr_pool_t *p);
873
874
/**
860
 * Find the shm of the worker as needed
875
 * Find the shm of the worker as needed
861
 * @param storage slotmem provider
876
 * @param storage slotmem provider
862
 * @param slot    slotmem instance
877
 * @param slot    slotmem instance
(-)a/modules/proxy/mod_proxy_balancer.c (-3 / +8 lines)
Lines 312-318 Link Here
312
    /*
312
    /*
313
     * If we found a value for stickysession, find the first '.' (or whatever
313
     * If we found a value for stickysession, find the first '.' (or whatever
314
     * sticky_separator is set to) within. Everything after '.' (if present)
314
     * sticky_separator is set to) within. Everything after '.' (if present)
315
     * is our route. 
315
     * is our route.
316
     */
316
     */
317
    if ((*route) && (balancer->s->sticky_separator != 0) && ((*route = strchr(*route, balancer->s->sticky_separator)) != NULL ))
317
    if ((*route) && (balancer->s->sticky_separator != 0) && ((*route = strchr(*route, balancer->s->sticky_separator)) != NULL ))
318
        (*route)++;
318
        (*route)++;
Lines 458-464 Link Here
458
static apr_status_t decrement_busy_count(void *worker_)
458
static apr_status_t decrement_busy_count(void *worker_)
459
{
459
{
460
    proxy_worker *worker = worker_;
460
    proxy_worker *worker = worker_;
461
    
461
462
    if (worker->s->busy) {
462
    if (worker->s->busy) {
463
        worker->s->busy--;
463
        worker->s->busy--;
464
    }
464
    }
Lines 1127-1132 Link Here
1127
        if ((val = apr_table_get(params, "w_status_H"))) {
1127
        if ((val = apr_table_get(params, "w_status_H"))) {
1128
            ap_proxy_set_wstatus(PROXY_WORKER_HOT_STANDBY_FLAG, atoi(val), wsel);
1128
            ap_proxy_set_wstatus(PROXY_WORKER_HOT_STANDBY_FLAG, atoi(val), wsel);
1129
        }
1129
        }
1130
        if ((val = apr_table_get(params, "w_status_R"))) {
1131
            ap_proxy_set_wstatus(PROXY_WORKER_HOT_SPARE_FLAG, atoi(val), wsel);
1132
        }
1130
        if ((val = apr_table_get(params, "w_status_S"))) {
1133
        if ((val = apr_table_get(params, "w_status_S"))) {
1131
            ap_proxy_set_wstatus(PROXY_WORKER_STOPPED_FLAG, atoi(val), wsel);
1134
            ap_proxy_set_wstatus(PROXY_WORKER_STOPPED_FLAG, atoi(val), wsel);
1132
        }
1135
        }
Lines 1651-1657 Link Here
1651
                     "<th>Ignore Errors</th>"
1654
                     "<th>Ignore Errors</th>"
1652
                     "<th>Draining Mode</th>"
1655
                     "<th>Draining Mode</th>"
1653
                     "<th>Disabled</th>"
1656
                     "<th>Disabled</th>"
1654
                     "<th>Hot Standby</th>", r);
1657
                     "<th>Hot Standby</th>"
1658
                     "<th>Hot Spare</th>", r);
1655
            if (hc_show_exprs_f) {
1659
            if (hc_show_exprs_f) {
1656
                ap_rputs("<th>HC Fail</th>", r);
1660
                ap_rputs("<th>HC Fail</th>", r);
1657
            }
1661
            }
Lines 1660-1665 Link Here
1660
            create_radio("w_status_N", (PROXY_WORKER_IS(wsel, PROXY_WORKER_DRAIN)), r);
1664
            create_radio("w_status_N", (PROXY_WORKER_IS(wsel, PROXY_WORKER_DRAIN)), r);
1661
            create_radio("w_status_D", (PROXY_WORKER_IS(wsel, PROXY_WORKER_DISABLED)), r);
1665
            create_radio("w_status_D", (PROXY_WORKER_IS(wsel, PROXY_WORKER_DISABLED)), r);
1662
            create_radio("w_status_H", (PROXY_WORKER_IS(wsel, PROXY_WORKER_HOT_STANDBY)), r);
1666
            create_radio("w_status_H", (PROXY_WORKER_IS(wsel, PROXY_WORKER_HOT_STANDBY)), r);
1667
            create_radio("w_status_R", (PROXY_WORKER_IS(wsel, PROXY_WORKER_HOT_SPARE)), r);
1663
            if (hc_show_exprs_f) {
1668
            if (hc_show_exprs_f) {
1664
                create_radio("w_status_C", (PROXY_WORKER_IS(wsel, PROXY_WORKER_HC_FAIL)), r);
1669
                create_radio("w_status_C", (PROXY_WORKER_IS(wsel, PROXY_WORKER_HC_FAIL)), r);
1665
            }
1670
            }
(-)a/modules/proxy/proxy_util.c (-5 / +93 lines)
Lines 1291-1296 Link Here
1291
    return APR_SUCCESS;
1291
    return APR_SUCCESS;
1292
}
1292
}
1293
1293
1294
PROXY_DECLARE(apr_array_header_t *) ap_proxy_balancer_usable_workers(proxy_balancer *balancer,
1295
                                                                     request_rec *r,
1296
                                                                     apr_pool_t *p)
1297
{
1298
    int i = 0;
1299
    int cur_lbset = 0;
1300
    int max_lbset = 0;
1301
    int unusable_workers = 0;
1302
    apr_array_header_t *workers;
1303
    apr_array_header_t *spares;
1304
    apr_array_header_t *standbys;
1305
    proxy_worker **worker;
1306
1307
    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, APLOGNO(10033)
1308
                 "proxy: Entering %s for BALANCER (%s)",
1309
                 balancer->lbmethod->name, balancer->s->name);
1310
1311
    workers = apr_array_make(p, balancer->workers->nelts, sizeof(proxy_worker*));
1312
    spares = apr_array_make(p, 1, sizeof(proxy_worker*));
1313
    standbys = apr_array_make(p, 1, sizeof(proxy_worker*));
1314
1315
    /* Process lbsets in order, only replacing unusable workers in a given lbset
1316
     * with available spares from the same lbset. Hot standbys will be used as a
1317
     * last resort when all other workers and spares are unavailable.
1318
     */
1319
    for (cur_lbset = 0; (workers->nelts == 0) && (cur_lbset <= max_lbset); cur_lbset++) {
1320
        unusable_workers = 0;
1321
        apr_array_clear(spares);
1322
        apr_array_clear(standbys);
1323
1324
        for (i = 0; i < balancer->workers->nelts; i++, worker++) {
1325
            worker = &APR_ARRAY_IDX(balancer->workers, i, proxy_worker *);
1326
1327
            if ((*worker)->s->lbset > max_lbset) {
1328
                max_lbset = (*worker)->s->lbset;
1329
            }
1330
1331
            if (
1332
                ((*worker)->s->lbset != cur_lbset)
1333
                || PROXY_WORKER_IS_DRAINING(*worker)
1334
            ) {
1335
                continue;
1336
            }
1337
1338
            /* If the worker is in error state run retry on that worker. It will
1339
             * be marked as operational if the retry timeout is elapsed.  The
1340
             * worker might still be unusable, but we try anyway.
1341
             */
1342
            if (!PROXY_WORKER_IS_USABLE(*worker)) {
1343
                ap_proxy_retry_worker("BALANCER", *worker, r->server);
1344
            }
1345
1346
            if (PROXY_WORKER_IS_SPARE(*worker)) {
1347
                if (PROXY_WORKER_IS_USABLE(*worker)) {
1348
                    APR_ARRAY_PUSH(spares, proxy_worker *) = *worker;
1349
                }
1350
            }
1351
            else if (PROXY_WORKER_IS_STANDBY(*worker)) {
1352
                if (PROXY_WORKER_IS_USABLE(*worker)) {
1353
                    APR_ARRAY_PUSH(standbys, proxy_worker *) = *worker;
1354
                }
1355
            }
1356
            else if (PROXY_WORKER_IS_USABLE(*worker)) {
1357
                APR_ARRAY_PUSH(workers, proxy_worker *) = *worker;
1358
            }
1359
            else {
1360
                unusable_workers++;
1361
            }
1362
        }
1363
1364
        /* Replace any unusable workers with any available spares. */
1365
        if (spares->nelts > 0) {
1366
            if (spares->nelts > unusable_workers) {
1367
                spares->nelts = unusable_workers;
1368
            }
1369
1370
            apr_array_cat(workers, spares);
1371
        }
1372
1373
        /* If no workers are available, use the standbys. */
1374
        if ((workers->nelts == 0) && (standbys->nelts > 0)) {
1375
            apr_array_cat(workers, standbys);
1376
        }
1377
    }
1378
1379
    return workers;
1380
}
1381
1294
/*
1382
/*
1295
 * CONNECTION related...
1383
 * CONNECTION related...
1296
 */
1384
 */
Lines 1976-1984 Link Here
1976
/*
2064
/*
1977
 * In the case of the reverse proxy, we need to see if we
2065
 * In the case of the reverse proxy, we need to see if we
1978
 * were passed a UDS url (eg: from mod_proxy) and adjust uds_path
2066
 * were passed a UDS url (eg: from mod_proxy) and adjust uds_path
1979
 * as required.  
2067
 * as required.
1980
 */
2068
 */
1981
static void fix_uds_filename(request_rec *r, char **url) 
2069
static void fix_uds_filename(request_rec *r, char **url)
1982
{
2070
{
1983
    char *ptr, *ptr2;
2071
    char *ptr, *ptr2;
1984
    if (!r || !r->filename) return;
2072
    if (!r || !r->filename) return;
Lines 2289-2297 Link Here
2289
     * Figure out if our passed in proxy_conn_rec has a usable
2377
     * Figure out if our passed in proxy_conn_rec has a usable
2290
     * address cached.
2378
     * address cached.
2291
     *
2379
     *
2292
     * TODO: Handle this much better... 
2380
     * TODO: Handle this much better...
2293
     *
2381
     *
2294
     * XXX: If generic workers are ever address-reusable, we need 
2382
     * XXX: If generic workers are ever address-reusable, we need
2295
     *      to check host and port on the conn and be careful about
2383
     *      to check host and port on the conn and be careful about
2296
     *      spilling the cached addr from the worker.
2384
     *      spilling the cached addr from the worker.
2297
     */
2385
     */
Lines 2432-2438 Link Here
2432
    }
2520
    }
2433
2521
2434
    /* check if ProxyBlock directive on this host */
2522
    /* check if ProxyBlock directive on this host */
2435
    if (OK != ap_proxy_checkproxyblock(r, conf, uri->hostname, 
2523
    if (OK != ap_proxy_checkproxyblock(r, conf, uri->hostname,
2436
                                       proxyname ? NULL : conn->addr)) {
2524
                                       proxyname ? NULL : conn->addr)) {
2437
        return ap_proxyerror(r, HTTP_FORBIDDEN,
2525
        return ap_proxyerror(r, HTTP_FORBIDDEN,
2438
                             "Connect to remote machine blocked");
2526
                             "Connect to remote machine blocked");

Return to bug 61140