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]
