DO NOT REPLY TO THIS EMAIL, BUT PLEASE POST YOUR BUG 
RELATED COMMENTS THROUGH THE WEB INTERFACE AVAILABLE AT
<http://issues.apache.org/bugzilla/show_bug.cgi?id=29649>.
ANY REPLY MADE TO THIS MESSAGE WILL NOT BE COLLECTED AND 
INSERTED IN THE BUG DATABASE.

http://issues.apache.org/bugzilla/show_bug.cgi?id=29649

Changes to mod_proxy for connection timeouts

           Summary: Changes to mod_proxy for connection timeouts
           Product: Apache httpd-1.3
           Version: 1.3.26
          Platform: Other
        OS/Version: Other
            Status: NEW
          Severity: Enhancement
          Priority: Other
         Component: mod_proxy
        AssignedTo: [email protected]
        ReportedBy: [EMAIL PROTECTED]
                CC: [EMAIL PROTECTED]


In working with a client experiencing performance issues, I came across the 
following issue. They use Apache to front end a large number of back end web 
appliactions such as CGI's, Websphere, Domino, Cold Fusion, Dynamo, Oracle, 
Webspeed, etc.

When the back end servers would stop answering, or even worse would accept the 
tcp connection but never reply back, the main Apache web server would hold the 
connection for the full server timeout period which was set (for good reason) 
at 5 minutes. Their fierwall, however, would terminate a connection after 40 
seconds if no data was transferred. Users would get firewall errors, hit reload 
and effectively open lock up a number of Apache processes for up to 5 minutes. 
The machine would hits its limit of apaches and the site would be inaccessible.

The obvious answer is to fix the back end systems. Unfortunately one was a 
Domino bug and they had to wait for IBM. I proposed a new architecture with a 
front end machine capable of handling their transaction load. In the short 
term, however, something had to be done (the client is a government adgency, 
and they never seem to move things fast enough through the buraceracy).

I therefore made some modifications in mod_proxy by identifying the sticking 
points, and created a new timeout value not based upon the server config that I 
could configure within the conf file so they could adjust it whatever firewall 
changes came down. This was an overwhelming success for the client and dropped 
their downtime on the main web server by over 95%.

This seemed to me to be a good idea to pass back into Apache.

I asked for a configurable or variable timeout change for the core. Here is the 
changes I made to mod_proxy. The changes are a bit ugly and  shoudl redo them 
to conform to the standards. What I am looking for at this moment is feedback 
as to the issue and solution. I'll make requierd changes to get this up to spec.

mod_proxy.c

81a82,83
> char *proxyLogFile;
>
220a223,225
> #ifdef EAPI
>     int rc;
> #endif /* EAPI */
227a233,240
> #ifdef EAPI
>     if (ap_hook_use("ap::mod_proxy::canon",
>                     AP_HOOK_SIG3(int,ptr,ptr),
>                     AP_HOOK_DECLINE(DECLINED),
>                     &rc, r, url) && rc != DECLINED)
>         return rc;
>     else
> #endif /* EAPI */
241a255,257
>     extern int proxyServerSocket;
>     proxyServerSocket = 0;
>
242a259,262
> #ifdef EAPI
>     ap_hook_use("ap::mod_proxy::init",
>                 AP_HOOK_SIG3(void,ptr,ptr), AP_HOOK_ALL, r, p);
> #endif
244a265,272
> #ifdef EAPI
> static void proxy_addmod(module *m)
> {
>     /* export: ap_proxy_http_canon() as `ap::mod_proxy::http::canon' */
>     ap_hook_configure("ap::mod_proxy::http::canon",
>                       AP_HOOK_SIG5(int,ptr,ptr,ptr,int), AP_HOOK_TOPMOST);
>     ap_hook_register("ap::mod_proxy::http::canon",
>                      ap_proxy_http_canon, AP_HOOK_NOCTX);
245a274,278
>     /* export: ap_proxy_http_handler() as `ap::mod_proxy::http::handler' */
>     ap_hook_configure("ap::mod_proxy::http::handler",
>                       AP_HOOK_SIG6(int,ptr,ptr,ptr,ptr,int), AP_HOOK_TOPMOST);
>     ap_hook_register("ap::mod_proxy::http::handler",
>                      ap_proxy_http_handler, AP_HOOK_NOCTX);
246a280,297
>     /* export: ap_proxyerror() as `ap::mod_proxy::error' */
>     ap_hook_configure("ap::mod_proxy::error",
>                       AP_HOOK_SIG3(int,ptr,ptr), AP_HOOK_TOPMOST);
>     ap_hook_register("ap::mod_proxy::error",
>                      ap_proxyerror, AP_HOOK_NOCTX);
>     return;
> }
>
> static void proxy_remmod(module *m)
> {
>       /* remove the hook references */
>     ap_hook_unregister("ap::mod_proxy::http::canon", ap_proxy_http_canon);
>     ap_hook_unregister("ap::mod_proxy::http::handler", ap_proxy_http_handler);
>     ap_hook_unregister("ap::mod_proxy::error", ap_proxyerror);
>     return;
> }
> #endif /* EAPI */
>
376a428,435
> #ifdef EAPI
>               if (!ap_hook_use("ap::mod_proxy::handler",
>                                AP_HOOK_SIG7(int,ptr,ptr,ptr,ptr,int,ptr),
>                                AP_HOOK_DECLINE(DECLINED),
>                                &rc, r, cr, url,
>                                ents[i].hostname, ents[i].port,
>                                ents[i].protocol) || rc == DECLINED) {
> #endif /* EAPI */
385a445,447
> #ifdef EAPI
>               }
> #endif /* EAPI */
399a462,469
> #ifdef EAPI
>     if (ap_hook_use("ap::mod_proxy::handler",
>                   AP_HOOK_SIG7(int,ptr,ptr,ptr,ptr,int,ptr),
>                   AP_HOOK_DECLINE(DECLINED),
>                   &rc, r, cr, url,
>                     NULL, 0, scheme) && rc != DECLINED)
>         return rc;
> #endif /* EAPI */
463a534,539
>     ps->connectTimeout = 0;
>     ps->headerTimeout = 0;
>     ps->bodyTimeout = 0;
>     ps->logFile = (char*) NULL;
>
>
499a576,579
>     ps->connectTimeout = (overrides->connectTimeout == 0) ? base-
>connectTimeout : overrides->connectTimeout;
>     ps->headerTimeout = (overrides->headerTimeout == 0) ? base-
>headerTimeout : overrides->headerTimeout;
>     ps->bodyTimeout = (overrides->bodyTimeout == 0) ? base->bodyTimeout : 
overrides->bodyTimeout;
>
922a1003,1040
> static const char *
>      set_connectTimeout(cmd_parms *parms, void *dummy, char *arg)
> {
>     proxy_server_conf *psf = ap_get_module_config(parms->server-
>module_config, &proxy_module);
>     psf->connectTimeout = atoi(arg);
>     return NULL;
> }
>
>
> static const char *
>      set_headerTimeout(cmd_parms *parms, void *dummy, char *arg)
> {
>     proxy_server_conf *psf = ap_get_module_config(parms->server-
>module_config, &proxy_module);
>     psf->headerTimeout = atoi(arg);
>     return NULL;
> }
> static const char *
>      set_bodyTimeout(cmd_parms *parms, void *dummy, char *arg)
> {
>     proxy_server_conf *psf = ap_get_module_config(parms->server-
>module_config, &proxy_module);
>     psf->bodyTimeout = atoi(arg);
>     return NULL;
> }
>
> static const char *
>      set_proxy_error_log(cmd_parms *parms, void *dummy, char *arg)
> {
>     extern char *proxyLogFile;
>     proxyLogFile = arg;
>     return NULL;
> }
>
>
>
>
>
>
930a1049,1056
>     {"ProxyErrorLogFile", set_proxy_error_log, NULL, RSRC_CONF, TAKE1,
>     "A Log file to write errors out to"},
>     {"ProxyConnectTimeout", set_connectTimeout, NULL, RSRC_CONF, TAKE1,
>     "A maximum time to allow for a connect to a proxy server"},
>     {"ProxyHeaderTimeout", set_headerTimeout, NULL, RSRC_CONF, TAKE1,
>     "A maximum time to allow for a header to be sent from a proxy server"},
>     {"ProxyBodyTimeout", set_bodyTimeout, NULL, RSRC_CONF, TAKE1,
>     "A maximum time to allow for a body to be sent from a proxy server"},
996a1123,1128
> #ifdef EAPI
>    ,proxy_addmod,             /* EAPI: add_module */
>     proxy_remmod,             /* EAPI: remove_module */
>     NULL,                     /* EAPI: rewrite_command */
>     NULL                      /* EAPI: new_connection  */
> #endif
>
> void
> getCurrentDateTime(char *in)
> {
>         time_t tempTime;
>         struct tm *theTime;
>
>         time(&tempTime);
>         theTime = localtime(&tempTime);
>
>         sprintf(in, "%04d/%02d/%02d %02d:%02d:%02d", theTime->tm_year + 1900, 
theTime->tm_mon + 1, theTime->tm_mday, theTime->tm_hour, theTime->tm_min, theTi
me
> ->tm_sec);
>
>         return;
> }
>
> void
> logIt(char *message)
> {
>       char theDate[1024];
>       FILE *fp;
>
>       getCurrentDateTime(theDate);
>
>       fp = fopen(proxyLogFile, "a");
>       if (fp)
>       {
>               fprintf(fp, "[%s] %s failed to respond and has been 
terminated.\n", theDate, message);
>               fclose(fp);
>       }
> }
>
>
>
> void
> cancelProxy(request_rec *theRequest)
> {
>       extern int proxyServerSocket;
>
>       logIt(theRequest->unparsed_uri);
>
>       if (proxyServerSocket != 0)
>       {
>               close(proxyServerSocket);
>       }
>
>       theRequest->status = HTTP_BAD_GATEWAY;
>       ap_proxyerror(theRequest, HTTP_BAD_GATEWAY, "Upstream Server 
Unavailable.");
>         ap_send_error_response(theRequest, 0);
>
>       return;
> }
>
>
>


mod_proxy.h

85a86,87
> int proxyServerSocket;
>
205a208,211
>     int connectTimeout;
>     int headerTimeout;
>     int bodyTimeout;
>     char *logFile;
344a351
>


proxy_http.c

60a61,72
> #include "httpd.h"
> #include "http_config.h"        /* for read_config */
> #include "http_protocol.h"      /* for read_request */
> #include "http_request.h"       /* for process_request */
> #include "http_conf_globals.h"
> #include "http_vhost.h"
> #include "util_script.h"        /* to force util_script.c linking */
> #include "util_uri.h"
> #include "scoreboard.h"
> #include "multithread.h"
>
>
172a185,189
> #ifdef EAPI
>     char *peer;
> #endif
>     extern int proxyServerSocket;
>     proxyServerSocket = 0;
193a211,216
> #ifdef EAPI
>     ap_hook_use("ap::mod_proxy::http::handler::set_destport",
>                 AP_HOOK_SIG2(int,ptr),
>                 AP_HOOK_TOPMOST,
>                 &destport, r);
> #endif /* EAPI */
230a254,256
> #ifdef EAPI
>       peer = ap_psprintf(p, "%s:%u", proxyhost, proxyport);
> #endif
236a263,265
> #ifdef EAPI
>       peer =  ap_psprintf(p, "%s:%u", desthost, destport);
> #endif
289c318
<                                     "Could not connect to remote machine: ",
---
>                                     "Could not cconnect to remote machine: ",
310a340,353
>     proxyServerSocket = sock;
>
> #ifdef EAPI
>     {
>         char *errmsg = NULL;
>         ap_hook_use("ap::mod_proxy::http::handler::new_connection",
>                     AP_HOOK_SIG4(ptr,ptr,ptr,ptr),
>                     AP_HOOK_DECLINE(NULL),
>                     &errmsg, r, f, peer);
>         if (errmsg != NULL)
>             return ap_proxyerror(r, HTTP_BAD_GATEWAY, errmsg);
>     }
> #endif /* EAPI */
>
313a357,371
> #ifdef EAPI
>     {
>       int rc = DECLINED;
>       ap_hook_use("ap::mod_proxy::http::handler::write_host_header",
>                   AP_HOOK_SIG6(int,ptr,ptr,ptr,int,ptr),
>                   AP_HOOK_DECLINE(DECLINED),
>                   &rc, r, f, desthost, destport, destportstr);
>         if (rc == DECLINED) {
>           if (destportstr != NULL && destport != DEFAULT_HTTP_PORT)
>               ap_bvputs(f, "Host: ", desthost, ":", destportstr, CRLF, NULL);
>           else
>               ap_bvputs(f, "Host: ", desthost, CRLF, NULL);
>         }
>     }
> #else /* EAPI */
318a377
> #endif /* EAPI */
436c495
<         ap_hard_timeout("proxy receive response status line", r);
---
>         ap_config_timeout(conf->connectTimeout, "proxy receive response 
status line", r);
467c526
<     ap_hard_timeout("proxy receive response headers", r);
---
>     ap_config_timeout(conf->connectTimeout, "proxy receive response headers", 
r);  // JEFF
617a677
> fclose(fp);
652a713,714
>
> // ap_variable_timeout


proxy_util.c

461a462,470
>
>     void *sconf;
>     proxy_server_conf *conf;
>     sconf = r->server->module_config;
>     conf = (proxy_server_conf *)ap_get_module_config(sconf, &proxy_module);
>
>
>
>
515c524
<             ap_hard_timeout("proxy recv body from upstream server", r);
---
>             ap_config_timeout(conf->headerTimeout, "proxy recv body from 
upstream server", r);
1366c1375,1383
<     ap_hard_timeout("proxy connect", r);
---
>     void *sconf;
>     proxy_server_conf *conf;
>
>     sconf = r->server->module_config;
>     conf = (proxy_server_conf *)ap_get_module_config(sconf, &proxy_module);
>
>
>
>     ap_config_timeout(conf->headerTimeout, "proxy connect", r);

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to