From: Willy Tarreau Date: Sun, 10 Jan 2010 13:46:16 +0000 (+0100) Subject: [MINOR] http: add a separate "http-keep-alive" timeout X-Git-Tag: v1.4-dev7~36 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b16a5746b7e3e952b0ef9fbd6121511a805d6d8a;p=thirdparty%2Fhaproxy.git [MINOR] http: add a separate "http-keep-alive" timeout This one is used to wait for next request after a response was sent to the client. --- diff --git a/doc/configuration.txt b/doc/configuration.txt index 528b991e03..c5dd1054be 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -835,6 +835,7 @@ timeout client X X X - timeout clitimeout X X X - (deprecated) timeout connect X - X X timeout contimeout X - X X (deprecated) +timeout http-keep-alive X X X X timeout http-request X X X X timeout queue X - X X timeout server X - X X @@ -2548,7 +2549,8 @@ no option http-server-close session or not. The accept date reported in the logs corresponds to the end of the previous request, and the request time corresponds to the time spent waiting for a new request. The keep-alive request time is still bound to the - timeout defined by "timeout http-request". + timeout defined by "timeout http-keep-alive" or "timeout http-request" if + not set. This option may be set both in a frontend and in a backend. It is enabled if at least one of the frontend or backend holding a connection has it enabled. @@ -4537,6 +4539,47 @@ timeout contimeout (deprecated) "timeout tarpit". +timeout http-keep-alive + Set the maximum allowed time to wait for a new HTTP request to appear + May be used in sections : defaults | frontend | listen | backend + yes | yes | yes | yes + Arguments : + is the timeout value specified in milliseconds by default, but + can be in any other unit if the number is suffixed by the unit, + as explained at the top of this document. + + By default, the time to wait for a new request in case of keep-alive is set + by "timeout http-request". However this is not always convenient because some + people want very short keep-alive timeouts in order to release connections + faster, and others prefer to have larger ones but still have short timeouts + once the request has started to present itself. + + The "http-keep-alive" timeout covers these needs. It will define how long to + wait for a new HTTP request to start coming after a response was sent. Once + the first byte of request has been seen, the "http-request" timeout is used + to wait for the complete request to come. Note that empty lines prior to a + new request do not refresh the timeout and are not counted as a new request. + + There is also another difference between the two timeouts : when a connection + expires during timeout http-keep-alive, no error is returned, the connection + just closes. If the connection expires in "http-request" while waiting for a + connection to complete, a HTTP 408 error is returned. + + In general it is optimal to set this value to a few tens to hundreds of + milliseconds, to allow users to fetch all objects of a page at once but + without waiting for further clicks. Also, if set to a very small value (eg: + 1 millisecond) it will probably only accept pipelined requests but not the + non-pipelined ones. It may be a nice trade-off for very large sites running + with tends to hundreds of thousands of clients. + + If this parameter is not set, the "http-request" timeout applies, and if both + are not set, "timeout client" still applies at the lower level. It should be + set in the frontend to take effect, unless the frontend is in TCP mode, in + which case the HTTP backend's timeout will be used. + + See also : "timeout http-request", "timeout client". + + timeout http-request Set the maximum allowed time to wait for a complete HTTP request May be used in sections : defaults | frontend | listen | backend @@ -4557,7 +4600,8 @@ timeout http-request Note that this timeout only applies to the header part of the request, and not to any data. As soon as the empty line is received, this timeout is not - used anymore. + used anymore. It is used again on keep-alive connections to wait for a second + request if "timeout http-keep-alive" is not set. Generally it is enough to set it to a few seconds, as most clients send the full request immediately upon connection. Add 3 or more seconds to cover TCP @@ -4570,7 +4614,7 @@ timeout http-request effect, unless the frontend is in TCP mode, in which case the HTTP backend's timeout will be used. - See also : "timeout client". + See also : "timeout http-keep-alive", "timeout client". timeout queue diff --git a/include/types/proxy.h b/include/types/proxy.h index 78449e7ea6..2ba298b8ee 100644 --- a/include/types/proxy.h +++ b/include/types/proxy.h @@ -201,6 +201,7 @@ struct proxy { int server; /* server I/O timeout (in ticks) */ int appsession; /* appsession cookie expiration */ int httpreq; /* maximum time for complete HTTP request */ + int httpka; /* maximum time for a new HTTP request when using keep-alive */ int check; /* maximum time for complete check */ } timeout; char *id, *desc; /* proxy id (name) and description */ diff --git a/src/cfgparse.c b/src/cfgparse.c index 58505ec27f..13e1cfdf8e 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -1006,6 +1006,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm) curproxy->timeout.client = defproxy.timeout.client; curproxy->timeout.tarpit = defproxy.timeout.tarpit; curproxy->timeout.httpreq = defproxy.timeout.httpreq; + curproxy->timeout.httpka = defproxy.timeout.httpka; curproxy->uri_auth = defproxy.uri_auth; curproxy->mon_net = defproxy.mon_net; curproxy->mon_mask = defproxy.mon_mask; @@ -1023,6 +1024,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm) curproxy->timeout.queue = defproxy.timeout.queue; curproxy->timeout.tarpit = defproxy.timeout.tarpit; curproxy->timeout.httpreq = defproxy.timeout.httpreq; + curproxy->timeout.httpka = defproxy.timeout.httpka; curproxy->source_addr = defproxy.source_addr; } diff --git a/src/proto_http.c b/src/proto_http.c index 582b562846..d62ac73fa1 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -2309,11 +2309,18 @@ int http_wait_for_request(struct session *s, struct buffer *req, int an_bit) * request timeout processing. */ txn->flags &= ~TX_WAIT_NEXT_RQ; + req->analyse_exp = TICK_ETERNITY; } /* just set the request timeout once at the beginning of the request */ - if (!tick_isset(req->analyse_exp)) - req->analyse_exp = tick_add_ifset(now_ms, s->be->timeout.httpreq); + if (!tick_isset(req->analyse_exp)) { + if ((msg->msg_state == HTTP_MSG_RQBEFORE) && + (txn->flags & TX_WAIT_NEXT_RQ) && + tick_isset(s->be->timeout.httpka)) + req->analyse_exp = tick_add(now_ms, s->be->timeout.httpka); + else + req->analyse_exp = tick_add_ifset(now_ms, s->be->timeout.httpreq); + } /* we're not ready yet */ return 0; @@ -2342,6 +2349,13 @@ int http_wait_for_request(struct session *s, struct buffer *req, int an_bit) * left uninitialized (for instance in the absence of headers). */ + if (txn->flags & TX_WAIT_NEXT_RQ) { + /* kill the pending keep-alive timeout */ + txn->flags &= ~TX_WAIT_NEXT_RQ; + req->analyse_exp = TICK_ETERNITY; + } + + /* Maybe we found in invalid header name while we were configured not * to block on that, so we have to capture it now. */ diff --git a/src/proxy.c b/src/proxy.c index 38eb2be899..5c5251f0b3 100644 --- a/src/proxy.c +++ b/src/proxy.c @@ -153,6 +153,10 @@ static int proxy_parse_timeout(char **args, int section, struct proxy *proxy, tv = &proxy->timeout.tarpit; td = &defpx->timeout.tarpit; cap = PR_CAP_FE | PR_CAP_BE; + } else if (!strcmp(args[0], "http-keep-alive")) { + tv = &proxy->timeout.httpka; + td = &defpx->timeout.httpka; + cap = PR_CAP_FE | PR_CAP_BE; } else if (!strcmp(args[0], "http-request")) { tv = &proxy->timeout.httpreq; td = &defpx->timeout.httpreq; @@ -182,7 +186,7 @@ static int proxy_parse_timeout(char **args, int section, struct proxy *proxy, } else { snprintf(err, errlen, "timeout '%s': must be 'client', 'server', 'connect', 'check', " - "'appsession', 'queue', 'http-request' or 'tarpit'", + "'appsession', 'queue', 'http-keep-alive', 'http-request' or 'tarpit'", args[0]); return -1; }