]> granicus.if.org Git - apache/commitdiff
Merge the following revisions from trunk:
authorEric Covener <covener@apache.org>
Wed, 14 Jan 2015 13:28:00 +0000 (13:28 +0000)
committerEric Covener <covener@apache.org>
Wed, 14 Jan 2015 13:28:00 +0000 (13:28 +0000)
     trunk patch: http://svn.apache.org/r1588544 (rewrite+UDS)
                  http://svn.apache.org/r1641636 ('using default worker' msg tweak)
                  http://svn.apache.org/r1647005 (tcp reuse)
                  http://svn.apache.org/r1647009 (uds reuse)
                  http://svn.apache.org/r1647334 (uds reuse fix)

    + 1 additional de_socketfy call in mod_proxy

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1651662 13f79535-47bb-0310-9956-ffa450edef68

CHANGES
docs/manual/mod/mod_proxy.xml
docs/manual/mod/mod_proxy_fcgi.xml
include/ap_mmn.h
modules/mappers/mod_rewrite.c
modules/proxy/mod_proxy.c
modules/proxy/mod_proxy.h
modules/proxy/mod_proxy_fcgi.c
modules/proxy/proxy_util.c

diff --git a/CHANGES b/CHANGES
index ca55b165fe1ef9c37abbd24ab5058898cd77b810..8714492413d6bb57ed83de5de053f58cdc04370d 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -22,6 +22,17 @@ Changes with Apache 2.4.11
      request headers earlier.  Adds "MergeTrailers" directive to restore
      legacy behavior.  [Edward Lu, Yann Ylavic, Joe Orton, Eric Covener]
 
+  *) mod_proxy_fcgi: Enable UDS backends configured with SetHandler/RewriteRule
+     to opt-in to connection reuse and other Proxy options via explicitly
+     declared "proxy workers" (<Proxy unix:... enablereuse=on max=...)
+     [Eric Covener]
+
+  *) mod_proxy: Add "enablereuse" option as the inverse of "disablereuse".
+     [Eric Covener]
+
+  *) mod_proxy_fcgi: Enable opt-in to TCP connection reuse by explicitly
+     setting proxy option disablereuse=off. [Eric Covener] PR 57378.
+
   *) event: Update the internal "connection id" when requests
      move from thread to thread. Reuse can confuse modules like
      mod_cgid. PR 57435. [Michael Thorpe <mike gistnet.com>]
index 6bd2803b348027f0a8374069fa8b2ad1b3b58a78..38ae444c79ba046381c03cb112deed08f133b82d 100644 (file)
@@ -1018,6 +1018,12 @@ ProxyPass /mirror/foo http://backend.example.com
     robin DNS. To disable connection pooling reuse,
     set this property value to <code>On</code>.
     </td></tr>
+    <tr><td>enablereuse</td>
+        <td>On</td>
+        <td>This is the inverse of 'disablereuse' above, provided as a
+        convenience for scheme handlers that require opt-in for connection
+        reuse (such as <module>mod_proxy_fcgi</module>).
+    </td></tr>
     <tr><td>flushpackets</td>
         <td>off</td>
         <td>Determines whether the proxy module will auto-flush the output
index 3dd95790a6e1de21ee29d6a8a59f56aaf88c9cc4..6fddb4403ceebdba7fa2d8996577be441db6e86a 100644 (file)
       </highlight>
     </example>
 
-    <p>This application should be able to handle multiple concurrent
-    connections.  <module>mod_proxy</module> enables connection reuse by
-    default, so after a request has been completed the connection will be
-    held open by that httpd child process and won't be reused until that
-    httpd process routes another request to the application.  If the
-    FastCGI application is unable to handle enough concurrent connections
-    from httpd, requests can block waiting for the application to close
-    an existing connection.  One way to resolve this is to disable connection
-    reuse on the <directive>ProxyPass</directive> directive, as shown in
-    the following example:</p>
-
-    <example><title>Single application instance, no connection reuse</title>
+    <p> <module>mod_proxy_fcgi</module> disables connection reuse by
+    default, so after a request has been completed the connection will NOT be
+    held open by that httpd child process and won't be reused.  If the
+    FastCGI application is able to handle concurrent connections
+    from httpd, you can opt-in to connection reuse as shown in the following
+    example:</p>
+
+    <example><title>Single application instance, connection reuse</title>
     <highlight language="config">
-      ProxyPass /myapp/ fcgi://localhost:4000/ disablereuse=on
+      ProxyPass /myapp/ fcgi://localhost:4000/ enablereuse=on
       </highlight>
     </example>
 
     <p> The following example passes the request URI as a filesystem 
     path for the PHP-FPM daemon to run. The request URL is implicitly added 
     to the 2nd parameter. The hostname and port following fcgi:// are where
-    PHP-FPM is listening.</p>
+    PHP-FPM is listening.  Connection pooling is enabled.</p>
     <example><title>PHP-FPM</title>
     <highlight language="config">
-      ProxyPassMatch ^/myapp/.*\.php(/.*)?$ fcgi://localhost:9000/var/www/
+      ProxyPassMatch ^/myapp/.*\.php(/.*)?$ fcgi://localhost:9000/var/www/ enablereuse=on
     </highlight>
     </example>
 
     the hostname and optional port following fcgi:// are ignored.</p>
     <example><title>PHP-FPM with UDS</title>
     <highlight language="config">
-      ProxyPassMatch ^/(.*\.php(/.*)?)$ "unix:/var/run/php5-fpm.sock|fcgi://localhost/var/www/"
+      # UDS does not currently support connection reuse
+      ProxyPassMatch ^/(.*\.php(/.*)?)$ "unix:/var/run/php5-fpm.sock|fcgi://localhost/var/www/" 
     </highlight>
     </example>
 
index b8f0bb5343bb25ef9abecb42285e5f732eeca7bf..ca433d6d4b0f212685bf37693e0e90ba3cfd94a7 100644 (file)
  * 20120211.38 (2.4.11-dev) Added ap_shutdown_conn().
  * 20120211.39 (2.4.11-dev) Add ap_proxy_connect_uds().
  * 20120211.40 (2.4.11-dev) Add ap_log_data(), ap_log_rdata(), etc.
+ * 20120211.41 (2.4.11-dev) Add ap_proxy_de_socketfy to mod_proxy.h
  */
 
 #define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */
 #ifndef MODULE_MAGIC_NUMBER_MAJOR
 #define MODULE_MAGIC_NUMBER_MAJOR 20120211
 #endif
-#define MODULE_MAGIC_NUMBER_MINOR 40                   /* 0...n */
+#define MODULE_MAGIC_NUMBER_MINOR 41                   /* 0...n */
 
 /**
  * Determine if the server's current MODULE_MAGIC_NUMBER is at least a
index 2fe9bf9e071de82a816363ee4c75dae1ef00139d..de0c11ba5409032f8c99f887ebd3df719807f40a 100644 (file)
@@ -4161,7 +4161,6 @@ static int apply_rewrite_rule(rewriterule_entry *p, rewrite_ctx *ctx)
                     r->filename));
 
         r->filename = apr_pstrcat(r->pool, "proxy:", r->filename, NULL);
-        apr_table_setn(r->notes, "rewrite-proxy", "1");
         return 1;
     }
 
index b0c1a9c0ceb14ff3ef91b58608c7f9cee2a6a08c..885a2c9eed8d6c1d8c858c90d77fee208399be4e 100644 (file)
@@ -174,6 +174,15 @@ static const char *set_worker_param(apr_pool_t *p,
             return "DisableReuse must be On|Off";
         worker->s->disablereuse_set = 1;
     }
+    else if (!strcasecmp(key, "enablereuse")) {
+        if (!strcasecmp(val, "on"))
+            worker->s->disablereuse = 0;
+        else if (!strcasecmp(val, "off"))
+            worker->s->disablereuse = 1;
+        else
+            return "EnableReuse must be On|Off";
+        worker->s->disablereuse_set = 1;
+    }
     else if (!strcasecmp(key, "route")) {
         /* Worker route.
          */
@@ -938,7 +947,6 @@ static int proxy_handler(request_rec *r)
             strncmp(r->filename, "proxy:", 6) != 0) {
             r->proxyreq = PROXYREQ_REVERSE;
             r->filename = apr_pstrcat(r->pool, r->handler, r->filename, NULL);
-            apr_table_setn(r->notes, "rewrite-proxy", "1");
         }
         else {
             return DECLINED;
@@ -1461,23 +1469,23 @@ static const char *
     return add_proxy(cmd, dummy, f1, r1, 1);
 }
 
-static char *de_socketfy(apr_pool_t *p, char *url)
+PROXY_DECLARE(const char *) ap_proxy_de_socketfy(apr_pool_t *p, const char *url)
 {
-    char *ptr;
+    const char *ptr;
     /*
      * We could be passed a URL during the config stage that contains
      * the UDS path... ignore it
      */
     if (!strncasecmp(url, "unix:", 5) &&
-        ((ptr = ap_strchr(url, '|')) != NULL)) {
+        ((ptr = ap_strchr_c(url, '|')) != NULL)) {
         /* move past the 'unix:...|' UDS path info */
-        char *ret, *c;
+        const char *ret, *c;
 
         ret = ptr + 1;
         /* special case: "unix:....|scheme:" is OK, expand
          * to "unix:....|scheme://localhost"
          * */
-        c = ap_strchr(ret, ':');
+        c = ap_strchr_c(ret, ':');
         if (c == NULL) {
             return NULL;
         }
@@ -1582,7 +1590,7 @@ static const char *
     }
 
     new->fake = apr_pstrdup(cmd->pool, f);
-    new->real = apr_pstrdup(cmd->pool, de_socketfy(cmd->pool, r));
+    new->real = apr_pstrdup(cmd->pool, ap_proxy_de_socketfy(cmd->pool, r));
     new->flags = flags;
     if (use_regex) {
         new->regex = ap_pregcomp(cmd->pool, f, AP_REG_EXTENDED);
@@ -1631,7 +1639,7 @@ static const char *
         new->balancer = balancer;
     }
     else {
-        proxy_worker *worker = ap_proxy_get_worker(cmd->temp_pool, NULL, conf, de_socketfy(cmd->pool, r));
+        proxy_worker *worker = ap_proxy_get_worker(cmd->temp_pool, NULL, conf, ap_proxy_de_socketfy(cmd->pool, r));
         int reuse = 0;
         if (!worker) {
             const char *err = ap_proxy_define_worker(cmd->pool, &worker, NULL, conf, r, 0);
@@ -2110,7 +2118,7 @@ static const char *add_member(cmd_parms *cmd, void *dummy, const char *arg)
     }
 
     /* Try to find existing worker */
-    worker = ap_proxy_get_worker(cmd->temp_pool, balancer, conf, de_socketfy(cmd->temp_pool, name));
+    worker = ap_proxy_get_worker(cmd->temp_pool, balancer, conf, ap_proxy_de_socketfy(cmd->temp_pool, name));
     if (!worker) {
         ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, cmd->server, APLOGNO(01147)
                      "Defining worker '%s' for balancer '%s'",
@@ -2196,7 +2204,7 @@ static const char *
         }
     }
     else {
-        worker = ap_proxy_get_worker(cmd->temp_pool, NULL, conf, de_socketfy(cmd->temp_pool, name));
+        worker = ap_proxy_get_worker(cmd->temp_pool, NULL, conf, ap_proxy_de_socketfy(cmd->temp_pool, name));
         if (!worker) {
             if (in_proxy_section) {
                 err = ap_proxy_define_worker(cmd->pool, &worker, NULL,
@@ -2336,7 +2344,7 @@ static const char *proxysection(cmd_parms *cmd, void *mconfig, const char *arg)
         }
         else {
             worker = ap_proxy_get_worker(cmd->temp_pool, NULL, sconf,
-                                         de_socketfy(cmd->temp_pool, (char*)conf->p));
+                                         ap_proxy_de_socketfy(cmd->temp_pool, (char*)conf->p));
             if (!worker) {
                 err = ap_proxy_define_worker(cmd->pool, &worker, NULL,
                                           sconf, conf->p, 0);
index 5b3473b02970bfe3dcfc80b121f98a361aafc23f..89f5c0951ae77feee80d1cb5d437c0d22242dcc3 100644 (file)
@@ -1023,6 +1023,14 @@ int ap_proxy_lb_workers(void);
  */
 PROXY_DECLARE(apr_port_t) ap_proxy_port_of_scheme(const char *scheme);
 
+/**
+ * Strip a unix domain socket (UDS) prefix from the input URL
+ * @param p             pool to allocate result from
+ * @param url           a URL potentially prefixed with a UDS path
+ * @return              URL with the UDS prefix removed
+ */
+PROXY_DECLARE(const char *) ap_proxy_de_socketfy(apr_pool_t *p, const char *url);
+
 extern module PROXY_DECLARE_DATA proxy_module;
 
 #endif /*MOD_PROXY_H*/
index 3079debf655d569306efd18ce0e6c85e46f62cba..54a4e8dc4813a07c6e4a882fc71109bb120683af 100644 (file)
@@ -835,11 +835,15 @@ static int proxy_fcgi_handler(request_rec *r, proxy_worker *worker,
         goto cleanup;
     }
 
-    /* XXX Setting close to 0 is a great way to end up with
-     *     timeouts at this point, since we lack good ways to manage the
-     *     back end fastcgi processes.  This should be revisited when we
-     *     have a better story on that part of things. */
+    /* This scheme handler does not reuse connections by default, to
+     * avoid tieing up a fastcgi that isn't expecting to work on 
+     * parallel requests.  But if the user went out of their way to
+     * type the default value of disablereuse=off, we'll allow it.
+     */  
     backend->close = 1;
+    if (worker->s->disablereuse_set && !worker->s->disablereuse) { 
+        backend->close = 0;
+    }
 
     /* Step Two: Make the Connection */
     if (ap_proxy_connect_backend(FCGI_SCHEME, backend, worker, r->server)) {
index 5809c02094bbb30174a3df423bd422d7e2d69d85..83131c12883add377fc9641005e3116b072b737f 100644 (file)
@@ -1528,6 +1528,8 @@ PROXY_DECLARE(proxy_worker *) ap_proxy_get_worker(apr_pool_t *p,
         return NULL;
     }
 
+    url = ap_proxy_de_socketfy(p, url);
+
     c = ap_strchr_c(url, ':');
     if (c == NULL || c[1] != '/' || c[2] != '/' || c[3] == '\0') {
         return NULL;
@@ -1901,6 +1903,40 @@ static int ap_proxy_retry_worker(const char *proxy_function, proxy_worker *worke
     }
 }
 
+/*
+ * In the case of the reverse proxy, we need to see if we
+ * were passed a UDS url (eg: from mod_proxy) and adjust uds_path
+ * as required.  
+ */
+static void fix_uds_filename(request_rec *r, char **url) 
+{
+    char *ptr, *ptr2;
+    if (!r || !r->filename) return;
+
+    if (!strncmp(r->filename, "proxy:", 6) &&
+            (ptr2 = ap_strcasestr(r->filename, "unix:")) &&
+            (ptr = ap_strchr(ptr2, '|'))) {
+        apr_uri_t urisock;
+        apr_status_t rv;
+        *ptr = '\0';
+        rv = apr_uri_parse(r->pool, ptr2, &urisock);
+        if (rv == APR_SUCCESS) {
+            char *rurl = ptr+1;
+            char *sockpath = ap_runtime_dir_relative(r->pool, urisock.path);
+            apr_table_setn(r->notes, "uds_path", sockpath);
+            *url = apr_pstrdup(r->pool, rurl); /* so we get the scheme for the uds */
+            /* r->filename starts w/ "proxy:", so add after that */
+            memmove(r->filename+6, rurl, strlen(rurl)+1);
+            ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r,
+                    "*: rewrite of url due to UDS(%s): %s (%s)",
+                    sockpath, *url, r->filename);
+        }
+        else {
+            *ptr = '|';
+        }
+    }
+}
+
 PROXY_DECLARE(int) ap_proxy_pre_request(proxy_worker **worker,
                                         proxy_balancer **balancer,
                                         request_rec *r,
@@ -1915,8 +1951,8 @@ PROXY_DECLARE(int) ap_proxy_pre_request(proxy_worker **worker,
             ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r,
                           "%s: found worker %s for %s",
                           (*worker)->s->scheme, (*worker)->s->name, *url);
-
             *balancer = NULL;
+            fix_uds_filename(r, url);
             access_status = OK;
         }
         else if (r->proxyreq == PROXYREQ_PROXY) {
@@ -1936,10 +1972,8 @@ PROXY_DECLARE(int) ap_proxy_pre_request(proxy_worker **worker,
         }
         else if (r->proxyreq == PROXYREQ_REVERSE) {
             if (conf->reverse) {
-                char *ptr;
-                char *ptr2;
                 ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r,
-                              "*: found reverse proxy worker for %s", *url);
+                              "*: using default reverse proxy worker for %s (no keepalive)", *url);
                 *balancer = NULL;
                 *worker = conf->reverse;
                 access_status = OK;
@@ -1949,36 +1983,7 @@ PROXY_DECLARE(int) ap_proxy_pre_request(proxy_worker **worker,
                  * regarding the Connection header in the request.
                  */
                 apr_table_setn(r->subprocess_env, "proxy-nokeepalive", "1");
-                /*
-                 * In the case of the generic reverse proxy, we need to see if we
-                 * were passed a UDS url (eg: from mod_proxy) and adjust uds_path
-                 * as required.
-                 *
-                 * NOTE: Here we use a quick note lookup, but we could also
-                 * check to see if r->filename starts with 'proxy:'
-                 */
-                if (apr_table_get(r->notes, "rewrite-proxy") &&
-                    (ptr2 = ap_strcasestr(r->filename, "unix:")) &&
-                    (ptr = ap_strchr(ptr2, '|'))) {
-                    apr_uri_t urisock;
-                    apr_status_t rv;
-                    *ptr = '\0';
-                    rv = apr_uri_parse(r->pool, ptr2, &urisock);
-                    if (rv == APR_SUCCESS) {
-                        char *rurl = ptr+1;
-                        char *sockpath = ap_runtime_dir_relative(r->pool, urisock.path);
-                        apr_table_setn(r->notes, "uds_path", sockpath);
-                        *url = apr_pstrdup(r->pool, rurl); /* so we get the scheme for the uds */
-                        /* r->filename starts w/ "proxy:", so add after that */
-                        memmove(r->filename+6, rurl, strlen(rurl)+1);
-                        ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r,
-                                      "*: rewrite of url due to UDS(%s): %s (%s)",
-                                      sockpath, *url, r->filename);
-                    }
-                    else {
-                        *ptr = '|';
-                    }
-                }
+                fix_uds_filename(r, url);
             }
         }
     }