]> granicus.if.org Git - apache/commitdiff
Allow for a simple socket check in addition to the
authorJim Jagielski <jim@apache.org>
Fri, 23 Aug 2013 16:48:42 +0000 (16:48 +0000)
committerJim Jagielski <jim@apache.org>
Fri, 23 Aug 2013 16:48:42 +0000 (16:48 +0000)
higher level protocol-level checks for backends...

Not sure if it makes sense to do both or not... Comments?

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1516930 13f79535-47bb-0310-9956-ffa450edef68

docs/manual/mod/mod_proxy.xml
modules/proxy/mod_proxy.c
modules/proxy/mod_proxy.h
modules/proxy/mod_proxy_ajp.c
modules/proxy/mod_proxy_http.c
modules/proxy/proxy_util.c

index aa77959658c01cab8da5803c84459bea15aeac5c..5a1ab09db45f182742aa12ba0b05af35a72d0d3f 100644 (file)
@@ -1003,7 +1003,9 @@ ProxyPass /mirror/foo http://backend.example.com
     <tr><td>ping</td>
         <td>0</td>
         <td>Ping property tells the webserver to "test" the connection to
-        the backend before forwarding the request. For AJP, it causes
+        the backend before forwarding the request. For negative values
+        the test is a simple socket check, for positive values it's
+        a more functional check, dependent upon the protocol. For AJP, it causes
         <module>mod_proxy_ajp</module>to send a <code>CPING</code>
         request on the ajp13 connection (implemented on Tomcat 3.3.2+, 4.1.28+
         and 5.0.13+). For HTTP, it causes <module>mod_proxy_http</module>
index a0a937f4fd9b4bdef4ee0c8bf8286f58cd193d32..96f32304c05327be47ed2a0cdf1a93afa3903a0f 100644 (file)
@@ -233,7 +233,7 @@ static const char *set_worker_param(apr_pool_t *p,
          */
         if (ap_timeout_parameter_parse(val, &timeout, "s") != APR_SUCCESS)
             return "Ping/Pong timeout has wrong format";
-        if (timeout < 1000)
+        if (timeout < 1000 && timeout >= 0)
             return "Ping/Pong timeout must be at least one millisecond";
         worker->s->ping_timeout = timeout;
         worker->s->ping_timeout_set = 1;
index 8ff4b8514966eb1c35a2073173b0d6b88c0704d0..e36f3f734cee5203511822df230c20a23be3ef85 100644 (file)
@@ -972,6 +972,13 @@ PROXY_DECLARE(int) ap_proxy_pass_brigade(apr_bucket_alloc_t *bucket_alloc,
 APR_DECLARE_OPTIONAL_FN(int, ap_proxy_clear_connection,
         (request_rec *r, apr_table_t *headers));
 
+
+/**
+ * @param socket        socket to test
+ * @return              TRUE if socket is connected/active
+ */
+PROXY_DECLARE(int) ap_proxy_is_socket_connected(apr_socket_t *socket);
+
 #define PROXY_LBMETHOD "proxylbmethod"
 
 /* The number of dynamic workers that can be added when reconfiguring.
index 46cda6ed10f86e18bbda2101b9fd0477e72bdb33..e78fdb0b5f386afdf70b10fac38c78418206241c 100644 (file)
@@ -759,22 +759,35 @@ static int proxy_ajp_handler(request_rec *r, proxy_worker *worker,
 
         /* Handle CPING/CPONG */
         if (worker->s->ping_timeout_set) {
-            status = ajp_handle_cping_cpong(backend->sock, r,
-                                            worker->s->ping_timeout);
-            /*
-             * In case the CPING / CPONG failed for the first time we might be
-             * just out of luck and got a faulty backend connection, but the
-             * backend might be healthy nevertheless. So ensure that the backend
-             * TCP connection gets closed and try it once again.
-             */
-            if (status != APR_SUCCESS) {
-                backend->close = 1;
-                ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, APLOGNO(00897)
-                              "cping/cpong failed to %pI (%s)",
-                              worker->cp->addr, worker->s->hostname);
-                status = HTTP_SERVICE_UNAVAILABLE;
-                retry++;
-                continue;
+            if (worker->s->ping_timeout_set < 0) {
+                if (!ap_proxy_is_socket_connected(backend->sock)) {
+                    backend->close = 1;
+                    ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, APLOGNO()
+                                  "socket check failed to %pI (%s)",
+                                  worker->cp->addr, worker->s->hostname);
+                    status = HTTP_SERVICE_UNAVAILABLE;
+                    retry++;
+                    continue;
+                }
+            }
+            else {
+                status = ajp_handle_cping_cpong(backend->sock, r,
+                                                worker->s->ping_timeout);
+                /*
+                 * In case the CPING / CPONG failed for the first time we might be
+                 * just out of luck and got a faulty backend connection, but the
+                 * backend might be healthy nevertheless. So ensure that the backend
+                 * TCP connection gets closed and try it once again.
+                 */
+                if (status != APR_SUCCESS) {
+                    backend->close = 1;
+                    ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, APLOGNO(00897)
+                                  "cping/cpong failed to %pI (%s)",
+                                  worker->cp->addr, worker->s->hostname);
+                    status = HTTP_SERVICE_UNAVAILABLE;
+                    retry++;
+                    continue;
+                }
             }
         }
         /* Step Three: Process the Request */
index 55dabba2af35489df4e2426e56a46b0d7b416e05..892aa2f3b84bfa8f714aac654af790c67da6b75d 100644 (file)
@@ -1975,13 +1975,25 @@ static int proxy_http_handler(request_rec *r, proxy_worker *worker,
             }
         }
 
+        /* Step Three-and-a-Half: See if the socket is still connected (if desired) */
+        if (worker->s->ping_timeout_set && worker->s->ping_timeout < 0 &&
+            !ap_proxy_is_socket_connected(backend->sock)) {
+            backend->close = 1;
+            ap_log_rerror(APLOG_MARK, APLOG_INFO, status, r, APLOGNO()
+                          "socket check failed to %pI (%s)",
+                          worker->cp->addr, worker->s->hostname);
+            retry++;
+            continue;
+        }
+
         /* Step Four: Send the Request
          * On the off-chance that we forced a 100-Continue as a
          * kinda HTTP ping test, allow for retries
          */
         if ((status = ap_proxy_http_request(p, r, backend, worker,
                                         conf, uri, locurl, server_portstr)) != OK) {
-            if ((status == HTTP_SERVICE_UNAVAILABLE) && worker->s->ping_timeout_set) {
+            if ((status == HTTP_SERVICE_UNAVAILABLE) && worker->s->ping_timeout_set &&
+                 worker->s->ping_timeout > 0) {
                 backend->close = 1;
                 ap_log_rerror(APLOG_MARK, APLOG_INFO, status, r, APLOGNO(01115)
                               "HTTP: 100-Continue failed to %pI (%s)",
index b7c10709f11ce16adbb8c43965a174eaefb54e73..1b62c5d97f78135d7db5b28cac3987551c6d6057 100644 (file)
@@ -2245,7 +2245,7 @@ ap_proxy_determine_connection(apr_pool_t *p, request_rec *r,
 #endif
 
 #if USE_ALTERNATE_IS_CONNECTED && defined(APR_MSG_PEEK)
-static int is_socket_connected(apr_socket_t *socket)
+PROXY_DECLARE(int) ap_proxy_is_socket_connected(apr_socket_t *socket)
 {
     apr_pollfd_t pfds[1];
     apr_status_t status;
@@ -2283,7 +2283,7 @@ static int is_socket_connected(apr_socket_t *socket)
 
 }
 #else
-static int is_socket_connected(apr_socket_t *sock)
+PROXY_DECLARE(int) ap_proxy_is_socket_connected(apr_socket_t *socket)
 
 {
     apr_size_t buffer_len = 1;
@@ -2466,7 +2466,7 @@ PROXY_DECLARE(int) ap_proxy_connect_backend(const char *proxy_function,
         (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module);
 
     if (conn->sock) {
-        if (!(connected = is_socket_connected(conn->sock))) {
+        if (!(connected = ap_proxy_is_socket_connected(conn->sock))) {
             socket_cleanup(conn);
             ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00951)
                          "%s: backend socket is disconnected.",