From 5fe1530a784f91bcfdb72a081895ce03a11a0e14 Mon Sep 17 00:00:00 2001 From: Jim Jagielski Date: Fri, 22 Jan 2016 20:23:42 +0000 Subject: [PATCH] Use threadpools and shove each hcheck to be done by a thread in the threadpool. If we don't have threadpools (either because APR lacks threads or we can'r create a threadpool) simply hcheck sequetially in the watchdog process. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1726304 13f79535-47bb-0310-9956-ffa450edef68 --- modules/proxy/mod_proxy_hcheck.c | 81 +++++++++++++++++++++++++++----- 1 file changed, 69 insertions(+), 12 deletions(-) diff --git a/modules/proxy/mod_proxy_hcheck.c b/modules/proxy/mod_proxy_hcheck.c index 82798fe521..e848b3275f 100644 --- a/modules/proxy/mod_proxy_hcheck.c +++ b/modules/proxy/mod_proxy_hcheck.c @@ -17,10 +17,22 @@ #include "mod_watchdog.h" #include "ap_slotmem.h" #include "ap_expr.h" +#if APR_HAS_THREADS +#include "apr_thread_pool.h" +#endif module AP_MODULE_DECLARE_DATA proxy_hcheck_module; #define HCHECK_WATHCHDOG_NAME ("_proxy_hcheck_") +#define HC_THREADPOOL_SIZE (16) + +/* Why? So we can easily set/clear HC_USE_THREADS during dev testing */ +#if APR_HAS_THREADS +#define HC_USE_THREADS 1 +#else +#define HC_USE_THREADS 0 +typedef void apr_thread_pool_t; +#endif typedef struct { char *name; @@ -44,6 +56,7 @@ typedef struct { apr_table_t *conditions; ap_watchdog_t *watchdog; apr_hash_t *hcworkers; + apr_thread_pool_t *hctp; server_rec *s; } sctx_t; @@ -54,6 +67,12 @@ typedef struct { proxy_worker *w; /* Pointer to the actual worker */ } wctx_t; +typedef struct { + sctx_t *ctx; + proxy_worker *worker; + apr_time_t now; +} baton_t; + static void *hc_create_config(apr_pool_t *p, server_rec *s) { sctx_t *ctx = (sctx_t *) apr_palloc(p, sizeof(sctx_t)); @@ -740,14 +759,18 @@ static apr_status_t hc_check_http(sctx_t *ctx, apr_pool_t *p, proxy_worker *work return backend_cleanup("HCOH", backend, ctx->s, status); } - -static void hc_check(sctx_t *ctx, apr_pool_t *p, apr_time_t now, - proxy_worker *worker) +static void *hc_check(apr_thread_t *thread, void *b) { + baton_t *baton = (baton_t *)b; + sctx_t *ctx = baton->ctx; + apr_time_t now = baton->now; + proxy_worker *worker = baton->worker; server_rec *s = ctx->s; apr_status_t rv; + apr_pool_t *p; + apr_pool_create(&p, ctx->p); ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(03256) - "Health checking %s", worker->s->name); + "%sHealth checking %s", (thread ? "Threaded " : ""), worker->s->name); switch (worker->s->method) { case TCP: @@ -766,8 +789,10 @@ static void hc_check(sctx_t *ctx, apr_pool_t *p, apr_time_t now, } if (rv == APR_ENOTIMPL) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(03257) - "Somehow tried to use unimplemented hcheck method: %d", (int)worker->s->method); - return; + "Somehow tried to use unimplemented hcheck method: %d", + (int)worker->s->method); + apr_pool_destroy(p); + return NULL; } /* what state are we in ? */ if (PROXY_WORKER_IS_HCFAILED(worker)) { @@ -777,7 +802,8 @@ static void hc_check(sctx_t *ctx, apr_pool_t *p, apr_time_t now, ap_proxy_set_wstatus(PROXY_WORKER_HC_FAIL_FLAG, 0, worker); worker->s->pcount = 0; ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, APLOGNO(03302) - "Health check ENABLING %s", worker->s->name); + "%sHealth check ENABLING %s", (thread ? "Threaded " : ""), + worker->s->name); } } @@ -789,11 +815,14 @@ static void hc_check(sctx_t *ctx, apr_pool_t *p, apr_time_t now, ap_proxy_set_wstatus(PROXY_WORKER_HC_FAIL_FLAG, 1, worker); worker->s->fcount = 0; ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, APLOGNO(03303) - "Health check DISABLING %s", worker->s->name); + "%sHealth check DISABLING %s", (thread ? "Threaded " : ""), + worker->s->name); } } } worker->s->updated = now; + apr_pool_destroy(p); + return NULL; } static apr_status_t hc_watchdog_callback(int state, void *data, @@ -805,12 +834,22 @@ static apr_status_t hc_watchdog_callback(int state, void *data, sctx_t *ctx = (sctx_t *)data; server_rec *s = ctx->s; proxy_server_conf *conf; - apr_pool_t *p; switch (state) { case AP_WATCHDOG_STATE_STARTING: ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(03258) "%s watchdog started.", HCHECK_WATHCHDOG_NAME); +#if HC_USE_THREADS + rv = apr_thread_pool_create(&ctx->hctp, HC_THREADPOOL_SIZE, + HC_THREADPOOL_SIZE,ctx->p); + if (rv != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_INFO, rv, s, APLOGNO() + "apr_thread_pool_create() with %d threads failed", + HC_THREADPOOL_SIZE); + /* we can continue on without the threadpools */ + ctx->hctp = NULL; + } +#endif break; case AP_WATCHDOG_STATE_RUNNING: @@ -820,7 +859,6 @@ static apr_status_t hc_watchdog_callback(int state, void *data, HCHECK_WATHCHDOG_NAME); if (s) { int i; - apr_pool_create(&p, pool); conf = (proxy_server_conf *) ap_get_module_config(s->module_config, &proxy_module); balancer = (proxy_balancer *)conf->balancers->elts; for (i = 0; i < conf->balancers->nelts; i++, balancer++) { @@ -836,15 +874,26 @@ static apr_status_t hc_watchdog_callback(int state, void *data, "Checking %s worker: %s [%d] (%pp)", balancer->s->name, worker->s->name, worker->s->method, worker); if ((worker->s->method != NONE) && (now > worker->s->updated + worker->s->interval)) { + baton_t *baton; if ((rv = hc_init_worker(ctx, worker)) != APR_SUCCESS) { return rv; } - hc_check(ctx, p, now, worker); + baton = apr_palloc(ctx->p, sizeof(baton_t)); + baton->ctx = ctx; + baton->now = now; + baton->worker = worker; + if (ctx->hctp) { +#if HC_USE_THREADS + rv = apr_thread_pool_push(ctx->hctp, hc_check, (void *)baton, APR_THREAD_TASK_PRIORITY_NORMAL, NULL); +#endif + ; + } else { + hc_check(NULL, baton); + } } workers++; } } - apr_pool_destroy(p); /* s = s->next; */ } break; @@ -853,6 +902,14 @@ static apr_status_t hc_watchdog_callback(int state, void *data, ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(03261) "stopping %s watchdog.", HCHECK_WATHCHDOG_NAME); +#if HC_USE_THREADS + rv = apr_thread_pool_destroy(ctx->hctp); + if (rv != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_INFO, rv, s, APLOGNO() + "apr_thread_pool_destroy() failed"); + } +#endif + ctx->hctp = NULL; break; } return rv; -- 2.40.0