]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
Add CPING to health check logic.
authorJean-Frederic Clere <jfclere@apache.org>
Wed, 10 Mar 2021 10:36:46 +0000 (10:36 +0000)
committerJean-Frederic Clere <jfclere@apache.org>
Wed, 10 Mar 2021 10:36:46 +0000 (10:36 +0000)
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1887415 13f79535-47bb-0310-9956-ffa450edef68

modules/proxy/mod_proxy.h
modules/proxy/mod_proxy_ajp.c
modules/proxy/mod_proxy_balancer.c
modules/proxy/mod_proxy_hcheck.c

index 1ad95309de240d4ea2ed79ec768fc24bdf1ef7cf..74d710295291548d8c7f63b7d9ce6569c4579538 100644 (file)
@@ -1347,6 +1347,15 @@ APR_DECLARE_OPTIONAL_FN(int, ap_proxy_clear_connection,
 APR_DECLARE_OPTIONAL_FN(apr_status_t, balancer_manage,
         (request_rec *, apr_table_t *params));
 
+/**
+ * Do a AJP CPING and wait for CPONG on the socket
+ *
+ */
+APR_DECLARE_OPTIONAL_FN(apr_status_t, ajp_handle_cping_cpong,
+        (apr_socket_t *sock, request_rec *r,
+         apr_interval_time_t timeout));
+
+
 /**
  * @param socket        socket to test
  * @return              TRUE if socket is connected/active
index 9ae0f437da318cb9ca926815eb5a038390b8b260..838ef7bbe3d39fae585338287eb1eb97f3604745 100644 (file)
@@ -831,6 +831,7 @@ static void ap_proxy_http_register_hook(apr_pool_t *p)
 {
     proxy_hook_scheme_handler(proxy_ajp_handler, NULL, NULL, APR_HOOK_FIRST);
     proxy_hook_canon_handler(proxy_ajp_canon, NULL, NULL, APR_HOOK_FIRST);
+    APR_REGISTER_OPTIONAL_FN(ajp_handle_cping_cpong);
 }
 
 AP_DECLARE_MODULE(proxy_ajp) = {
index 0bff999d809a00b94ab7c87b49f7e4f619797b99..fd361bcca6d3c2d43aeb93e4c2890195efc3b839 100644 (file)
@@ -1087,6 +1087,8 @@ static void push2table(const char *input, apr_table_t *params,
         }
         ap_unescape_url(key);
         ap_unescape_url(val);
+        /* hcuri, worker name, balancer name, at least  are escaped when building the form, so twice */
+        ap_unescape_url(val);
         if (allowed == NULL) { /* allow all */
             apr_table_set(params, key, val);
         }
@@ -1215,7 +1217,7 @@ static int balancer_process_balancer_worker(request_rec *r, proxy_server_conf *c
                 *wsel->s->hcexpr = '\0';
         }
         /* If the health check method doesn't support an expr, then null it */
-        if (wsel->s->method == NONE || wsel->s->method == TCP) {
+        if (wsel->s->method == NONE || wsel->s->method == TCP || wsel->s->method == CPING) {
             *wsel->s->hcexpr = '\0';
         }
         /* if enabling, we need to reset all lb params */
index 6f9902ea3392f1b89ddacd9f19af194b9b066b6c..9986f1a9bd78a72a41be05ace952410ad9a52168 100644 (file)
@@ -75,6 +75,8 @@ typedef struct {
     apr_time_t *now;
 } baton_t;
 
+static APR_OPTIONAL_FN_TYPE(ajp_handle_cping_cpong) *ajp_handle_cping_cpong = NULL;
+
 static void *hc_create_config(apr_pool_t *p, server_rec *s)
 {
     sctx_t *ctx = apr_pcalloc(p, sizeof(sctx_t));
@@ -613,6 +615,39 @@ static int hc_get_backend(const char *proxy_function, proxy_conn_rec **backend,
     return hc_determine_connection(ctx, hc, &(*backend)->addr, ptemp);
 }
 
+static apr_status_t hc_check_cping(baton_t *baton)
+{
+    int status;
+    sctx_t *ctx = baton->ctx;
+    proxy_worker *hc = baton->hc;
+    proxy_conn_rec *backend = NULL;
+    apr_pool_t *ptemp = baton->ptemp;
+    request_rec *r;
+    apr_interval_time_t timeout;
+
+    if (!ajp_handle_cping_cpong) {
+        return APR_ENOTIMPL;
+    }
+
+    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, baton->ctx->s, "HCCPING starting");
+    if ((status = hc_get_backend("HCCPING", &backend, hc, ctx, baton->ptemp)) != OK) {
+        return backend_cleanup("HCCPING", backend, ctx->s, status);
+    }
+    if ((status = ap_proxy_connect_backend("HCCPING", backend, hc, ctx->s)) != OK) {
+        return backend_cleanup("HCCPING", backend, ctx->s, status);
+    }
+    r = create_request_rec(ptemp, ctx->s, baton->balancer, "CPING");
+    if ((status = ap_proxy_connection_create_ex("HCCPING", backend, r)) != OK) {
+        return backend_cleanup("HCCPING", backend, ctx->s, status);
+    }
+    set_request_connection(r, backend->connection);
+
+    timeout = apr_time_from_sec(10); /* 10 seconds */
+    status = ajp_handle_cping_cpong(backend->sock, r, timeout);
+    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, baton->ctx->s, "HCCPING done %d", status);
+    return backend_cleanup("HCCPING", backend, ctx->s, status);
+}
+
 static apr_status_t hc_check_tcp(baton_t *baton)
 {
     int status;
@@ -848,6 +883,9 @@ static void * APR_THREAD_FUNC hc_check(apr_thread_t *thread, void *b)
     if (hc->s->method == TCP) {
         rv = hc_check_tcp(baton);
     }
+    else if (hc->s->method == CPING) {
+        rv = hc_check_cping(baton);
+    }
     else {
         rv = hc_check_http(baton);
     }
@@ -1075,6 +1113,18 @@ static int hc_post_config(apr_pool_t *p, apr_pool_t *plog,
                      "watchdog callback registered (%s for %s)", HCHECK_WATHCHDOG_NAME, s->server_hostname);
         s = s->next;
     }
+
+    ajp_handle_cping_cpong = APR_RETRIEVE_OPTIONAL_FN(ajp_handle_cping_cpong);
+    if (ajp_handle_cping_cpong) {
+       proxy_hcmethods_t *method = proxy_hcmethods;
+       for (; method->name; method++) {
+           if (method->method == CPING) {
+               method->implemented = 1;
+               break;
+           }
+       }
+    }
+
     return OK;
 }