MEDIUM: session: add support for tunnel timeouts

Tunnel timeouts are used when TCP connections are forwarded, or
when forwarding upgraded HTTP connections (WebSocket) as well as
CONNECT requests to proxies.

This timeout allows long-lived sessions to be supported without
having to set large timeouts to normal requests.
This commit is contained in:
Willy Tarreau 2012-05-12 12:50:00 +02:00
parent 2f5b6fc090
commit ce887fd3b2
6 changed files with 74 additions and 8 deletions

View File

@ -1117,6 +1117,7 @@ timeout queue X - X X
timeout server X - X X timeout server X - X X
timeout srvtimeout (deprecated) X - X X timeout srvtimeout (deprecated) X - X X
timeout tarpit X X X X timeout tarpit X X X X
timeout tunnel X - X X
transparent (deprecated) X - X X transparent (deprecated) X - X X
unique-id-format X X X - unique-id-format X X X -
unique-id-header X X X - unique-id-header X X X -
@ -3551,7 +3552,7 @@ no option independant-streams
data sent to the server. Doing so will typically break large HTTP posts from data sent to the server. Doing so will typically break large HTTP posts from
slow lines, so use it with caution. slow lines, so use it with caution.
See also : "timeout client" and "timeout server" See also : "timeout client", "timeout server" and "timeout tunnel"
option ldap-check option ldap-check
@ -5014,7 +5015,8 @@ srvtimeout <timeout> (deprecated)
This parameter is provided for compatibility but is currently deprecated. This parameter is provided for compatibility but is currently deprecated.
Please use "timeout server" instead. Please use "timeout server" instead.
See also : "timeout server", "timeout client" and "clitimeout". See also : "timeout server", "timeout tunnel", "timeout client" and
"clitimeout".
stats admin { if | unless } <cond> stats admin { if | unless } <cond>
@ -6334,7 +6336,9 @@ timeout clitimeout <timeout> (deprecated)
client timeout remains equal to the server timeout in order to avoid complex client timeout remains equal to the server timeout in order to avoid complex
situations to debug. It is a good practice to cover one or several TCP packet situations to debug. It is a good practice to cover one or several TCP packet
losses by specifying timeouts that are slightly above multiples of 3 seconds losses by specifying timeouts that are slightly above multiples of 3 seconds
(eg: 4 or 5 seconds). (eg: 4 or 5 seconds). If some long-lived sessions are mixed with short-lived
sessions (eg: WebSocket and HTTP), it's worth considering "timeout tunnel",
which overrides "timeout client" and "timeout server" for tunnels.
This parameter is specific to frontends, but can be specified once for all in This parameter is specific to frontends, but can be specified once for all in
"defaults" sections. This is in fact one of the easiest solutions not to "defaults" sections. This is in fact one of the easiest solutions not to
@ -6347,7 +6351,7 @@ timeout clitimeout <timeout> (deprecated)
to use it to write new configurations. The form "timeout clitimeout" is to use it to write new configurations. The form "timeout clitimeout" is
provided only by backwards compatibility but its use is strongly discouraged. provided only by backwards compatibility but its use is strongly discouraged.
See also : "clitimeout", "timeout server". See also : "clitimeout", "timeout server", "timeout tunnel".
timeout connect <timeout> timeout connect <timeout>
@ -6508,7 +6512,10 @@ timeout srvtimeout <timeout> (deprecated)
order to avoid complex situations to debug. Whatever the expected server order to avoid complex situations to debug. Whatever the expected server
response times, it is a good practice to cover at least one or several TCP response times, it is a good practice to cover at least one or several TCP
packet losses by specifying timeouts that are slightly above multiples of 3 packet losses by specifying timeouts that are slightly above multiples of 3
seconds (eg: 4 or 5 seconds minimum). seconds (eg: 4 or 5 seconds minimum). If some long-lived sessions are mixed
with short-lived sessions (eg: WebSocket and HTTP), it's worth considering
"timeout tunnel", which overrides "timeout client" and "timeout server" for
tunnels.
This parameter is specific to backends, but can be specified once for all in This parameter is specific to backends, but can be specified once for all in
"defaults" sections. This is in fact one of the easiest solutions not to "defaults" sections. This is in fact one of the easiest solutions not to
@ -6521,7 +6528,7 @@ timeout srvtimeout <timeout> (deprecated)
to use it to write new configurations. The form "timeout srvtimeout" is to use it to write new configurations. The form "timeout srvtimeout" is
provided only by backwards compatibility but its use is strongly discouraged. provided only by backwards compatibility but its use is strongly discouraged.
See also : "srvtimeout", "timeout client". See also : "srvtimeout", "timeout client" and "timeout tunnel".
timeout tarpit <timeout> timeout tarpit <timeout>
@ -6546,6 +6553,47 @@ timeout tarpit <timeout>
See also : "timeout connect", "contimeout". See also : "timeout connect", "contimeout".
timeout tunnel <timeout>
Set the maximum inactivity time on the client and server side for tunnels.
May be used in sections : defaults | frontend | listen | backend
yes | no | yes | yes
Arguments :
<timeout> 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.
The tunnel timeout applies when a bidirectionnal connection is established
between a client and a server, and the connection remains inactive in both
directions. This timeout supersedes both the client and server timeouts once
the connection becomes a tunnel. In TCP, this timeout is used as soon as no
analyser remains attached to either connection (eg: tcp content rules are
accepted). In HTTP, this timeout is used when a connection is upgraded (eg:
when switching to the WebSocket protocol, or forwarding a CONNECT request
to a proxy), or after the first response when no keepalive/close option is
specified.
The value is specified in milliseconds by default, but can be in any other
unit if the number is suffixed by the unit, as specified at the top of this
document. Whatever the expected normal idle time, it is a good practice to
cover at least one or several TCP packet losses by specifying timeouts that
are slightly above multiples of 3 seconds (eg: 4 or 5 seconds minimum).
This parameter is specific to backends, but can be specified once for all in
"defaults" sections. This is in fact one of the easiest solutions not to
forget about it.
Example :
defaults http
option http-server-close
timeout connect 5s
timeout client 30s
timeout client 30s
timeout server 30s
timeout tunnel 1h # timeout to use with WebSocket and CONNECT
See also : "timeout client", "timeout server".
transparent (deprecated) transparent (deprecated)
Enable client-side transparent proxying Enable client-side transparent proxying
May be used in sections : defaults | frontend | listen | backend May be used in sections : defaults | frontend | listen | backend

View File

@ -69,6 +69,7 @@ static inline void proxy_reset_timeouts(struct proxy *proxy)
proxy->timeout.appsession = TICK_ETERNITY; proxy->timeout.appsession = TICK_ETERNITY;
proxy->timeout.httpreq = TICK_ETERNITY; proxy->timeout.httpreq = TICK_ETERNITY;
proxy->timeout.check = TICK_ETERNITY; proxy->timeout.check = TICK_ETERNITY;
proxy->timeout.tunnel = TICK_ETERNITY;
} }
/* increase the number of cumulated connections received on the designated frontend */ /* increase the number of cumulated connections received on the designated frontend */

View File

@ -263,6 +263,7 @@ struct proxy {
int httpreq; /* maximum time for complete HTTP request */ int httpreq; /* maximum time for complete HTTP request */
int httpka; /* maximum time for a new HTTP request when using keep-alive */ int httpka; /* maximum time for a new HTTP request when using keep-alive */
int check; /* maximum time for complete check */ int check; /* maximum time for complete check */
int tunnel; /* I/O timeout to use in tunnel mode (in ticks) */
} timeout; } timeout;
char *id, *desc; /* proxy id (name) and description */ char *id, *desc; /* proxy id (name) and description */
struct list pendconns; /* pending connections with no server assigned yet */ struct list pendconns; /* pending connections with no server assigned yet */

View File

@ -1547,6 +1547,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
curproxy->timeout.tarpit = defproxy.timeout.tarpit; curproxy->timeout.tarpit = defproxy.timeout.tarpit;
curproxy->timeout.httpreq = defproxy.timeout.httpreq; curproxy->timeout.httpreq = defproxy.timeout.httpreq;
curproxy->timeout.httpka = defproxy.timeout.httpka; curproxy->timeout.httpka = defproxy.timeout.httpka;
curproxy->timeout.tunnel = defproxy.timeout.tunnel;
curproxy->source_addr = defproxy.source_addr; curproxy->source_addr = defproxy.source_addr;
} }
@ -6127,7 +6128,8 @@ int check_config_validity()
if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) && if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
(((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) || (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
((curproxy->cap & PR_CAP_BE) && (curproxy->srv) && ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
(!curproxy->timeout.connect || !curproxy->timeout.server)))) { (!curproxy->timeout.connect ||
(!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Warning("config : missing timeouts for %s '%s'.\n" Warning("config : missing timeouts for %s '%s'.\n"
" | While not properly invalid, you will certainly encounter various problems\n" " | While not properly invalid, you will certainly encounter various problems\n"
" | with such a configuration. To fix this, please ensure that all following\n" " | with such a configuration. To fix this, please ensure that all following\n"

View File

@ -183,10 +183,14 @@ static int proxy_parse_timeout(char **args, int section, struct proxy *proxy,
tv = &proxy->timeout.queue; tv = &proxy->timeout.queue;
td = &defpx->timeout.queue; td = &defpx->timeout.queue;
cap = PR_CAP_BE; cap = PR_CAP_BE;
} else if (!strcmp(args[0], "tunnel")) {
tv = &proxy->timeout.tunnel;
td = &defpx->timeout.tunnel;
cap = PR_CAP_BE;
} else { } else {
memprintf(err, memprintf(err,
"'timeout' supports 'client', 'server', 'connect', 'check', " "'timeout' supports 'client', 'server', 'connect', 'check', "
"'queue', 'http-keep-alive', 'http-request' or 'tarpit', (got '%s')", "'queue', 'http-keep-alive', 'http-request', 'tunnel' or 'tarpit', (got '%s')",
args[0]); args[0]);
return -1; return -1;
} }

View File

@ -2001,6 +2001,16 @@ struct task *process_session(struct task *t)
*/ */
if (!(s->rep->flags & (BF_SHUTR|BF_SHUTW_NOW))) if (!(s->rep->flags & (BF_SHUTR|BF_SHUTW_NOW)))
buffer_forward(s->rep, BUF_INFINITE_FORWARD); buffer_forward(s->rep, BUF_INFINITE_FORWARD);
/* if we have no analyser anymore in any direction and have a
* tunnel timeout set, use it now.
*/
if (!s->req->analysers && s->be->timeout.tunnel) {
s->req->rto = s->req->wto = s->rep->rto = s->rep->wto =
s->be->timeout.tunnel;
s->req->rex = s->req->wex = s->rep->rex = s->rep->wex =
tick_add(now_ms, s->be->timeout.tunnel);
}
} }
/* check if it is wise to enable kernel splicing to forward response data */ /* check if it is wise to enable kernel splicing to forward response data */