On 04/11/2018 02:11 PM, [email protected] wrote: > Author: jhriggs > Date: Wed Apr 11 12:11:05 2018 > New Revision: 1828890 > > URL: http://svn.apache.org/viewvc?rev=1828890&view=rev > Log: > mod_proxy_balancer: Add hot spare member type and corresponding flag (R). Hot > spare members are > used as drop-in replacements for unusable workers in the same load balancer > set. This differs > from hot standbys which are only used when all workers in a set are unusable. > PR 61140. > > Modified: > httpd/httpd/trunk/CHANGES > httpd/httpd/trunk/docs/log-message-tags/next-number > httpd/httpd/trunk/docs/manual/howto/reverse_proxy.xml > httpd/httpd/trunk/docs/manual/mod/mod_proxy.xml > httpd/httpd/trunk/modules/proxy/balancers/mod_lbmethod_bybusyness.c > httpd/httpd/trunk/modules/proxy/balancers/mod_lbmethod_byrequests.c > httpd/httpd/trunk/modules/proxy/balancers/mod_lbmethod_bytraffic.c > httpd/httpd/trunk/modules/proxy/mod_proxy.c > httpd/httpd/trunk/modules/proxy/mod_proxy.h > httpd/httpd/trunk/modules/proxy/mod_proxy_balancer.c > httpd/httpd/trunk/modules/proxy/proxy_util.c >
> Modified: httpd/httpd/trunk/modules/proxy/proxy_util.c > URL: > http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/proxy/proxy_util.c?rev=1828890&r1=1828889&r2=1828890&view=diff > ============================================================================== > --- httpd/httpd/trunk/modules/proxy/proxy_util.c (original) > +++ httpd/httpd/trunk/modules/proxy/proxy_util.c Wed Apr 11 12:11:05 2018 > @@ -1293,6 +1294,121 @@ PROXY_DECLARE(apr_status_t) ap_proxy_ini > return APR_SUCCESS; > } > > +PROXY_DECLARE(proxy_worker *) > ap_proxy_balancer_get_best_worker(proxy_balancer *balancer, > + request_rec > *r, > + > proxy_is_best_callback_fn_t *is_best, > + void *baton) > +{ > + int i = 0; > + int cur_lbset = 0; > + int max_lbset = 0; > + int unusable_workers = 0; > + apr_pool_t *tpool = NULL; > + apr_array_header_t *spares = NULL; > + apr_array_header_t *standbys = NULL; > + proxy_worker *worker = NULL; > + proxy_worker *best_worker = NULL; > + > + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, APLOGNO(10122) > + "proxy: Entering %s for BALANCER (%s)", > + balancer->lbmethod->name, balancer->s->name); > + > + apr_pool_create(&tpool, r->pool); > + > + spares = apr_array_make(tpool, 1, sizeof(proxy_worker*)); > + standbys = apr_array_make(tpool, 1, sizeof(proxy_worker*)); > + > + /* Process lbsets in order, only replacing unusable workers in a given > lbset > + * with available spares from the same lbset. Hot standbys will be used > as a > + * last resort when all other workers and spares are unavailable. > + */ > + for (cur_lbset = 0; !best_worker && (cur_lbset <= max_lbset); > cur_lbset++) { > + unusable_workers = 0; > + apr_array_clear(spares); > + apr_array_clear(standbys); > + > + for (i = 0; i < balancer->workers->nelts; i++) { > + worker = APR_ARRAY_IDX(balancer->workers, i, proxy_worker *); > + > + if (worker->s->lbset > max_lbset) { > + max_lbset = worker->s->lbset; > + } > + > + if (worker->s->lbset != cur_lbset) { > + continue; > + } > + > + /* A draining worker that is neither a spare nor a standby > should be > + * considered unusable to be replaced by spares. > + */ > + if (PROXY_WORKER_IS_DRAINING(worker)) { > + if (!PROXY_WORKER_IS_SPARE(worker) && > !PROXY_WORKER_IS_STANDBY(worker)) { > + unusable_workers++; > + } > + > + 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); > + } > + > + if (PROXY_WORKER_IS_SPARE(worker)) { > + if (PROXY_WORKER_IS_USABLE(worker)) { > + APR_ARRAY_PUSH(spares, proxy_worker *) = worker; > + } > + } > + else if (PROXY_WORKER_IS_STANDBY(worker)) { > + if (PROXY_WORKER_IS_USABLE(worker)) { > + APR_ARRAY_PUSH(standbys, proxy_worker *) = worker; > + } > + } > + else if (PROXY_WORKER_IS_USABLE(worker)) { > + if (is_best(worker, best_worker, baton)) { > + best_worker = worker; > + } > + } > + else { > + unusable_workers++; > + } > + } > + > + /* Check if any spares are best. */ > + for (i = 0; (i < spares->nelts) && (i < unusable_workers); i++) { Couldn't we save MIN(spares->nelts, unusable_workers) before the loop and check that i < MIN in the loop? Regards RĂ¼diger
