mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2026-05-05 13:06:10 +02:00
MEDIUM: server: implement TCP_USER_TIMEOUT on the server
This is equivalent to commit 2af207a ("MEDIUM: tcp: implement tcp-ut
bind option to set TCP_USER_TIMEOUT") except that this time it works
on the server side. The purpose is to detect dead server connections
even when checks are rare, disabled, or after a soft reload (since
checks are disabled there as well), and to ensure client connections
will get killed faster.
This commit is contained in:
parent
061b5ded28
commit
163d4620c6
@ -10598,6 +10598,21 @@ ssl
|
||||
|
||||
Supported in default-server: No
|
||||
|
||||
tcp-ut <delay>
|
||||
Sets the TCP User Timeout for all outgoing connections to this server. This
|
||||
option is available on Linux since version 2.6.37. It allows haproxy to
|
||||
configure a timeout for sockets which contain data not receiving an
|
||||
acknoledgement for the configured delay. This is especially useful on
|
||||
long-lived connections experiencing long idle periods such as remote
|
||||
terminals or database connection pools, where the client and server timeouts
|
||||
must remain high to allow a long period of idle, but where it is important to
|
||||
detect that the server has disappeared in order to release all resources
|
||||
associated with its connection (and the client's session). One typical use
|
||||
case is also to force dead server connections to die when health checks are
|
||||
too slow or during a soft reload since health checks are then disabled. The
|
||||
argument is a delay expressed in milliseconds by default. This only works for
|
||||
regular TCP connections, and is ignored for other protocols.
|
||||
|
||||
track [<proxy>/]<server>
|
||||
This option enables ability to set the current state of the server by tracking
|
||||
another one. It is possible to track a server which itself tracks another
|
||||
|
||||
@ -216,6 +216,7 @@ struct server {
|
||||
time_t last_change; /* last time, when the state was changed */
|
||||
|
||||
int puid; /* proxy-unique server ID, used for SNMP, and "first" LB algo */
|
||||
int tcp_ut; /* for TCP, user timeout */
|
||||
|
||||
struct check check; /* health-check specific configuration */
|
||||
struct check agent; /* agent specific configuration */
|
||||
|
||||
@ -39,7 +39,6 @@
|
||||
|
||||
#include <types/global.h>
|
||||
#include <types/capture.h>
|
||||
#include <types/server.h>
|
||||
#include <types/connection.h>
|
||||
|
||||
#include <proto/acl.h>
|
||||
@ -56,6 +55,7 @@
|
||||
#include <proto/proto_tcp.h>
|
||||
#include <proto/proxy.h>
|
||||
#include <proto/sample.h>
|
||||
#include <proto/server.h>
|
||||
#include <proto/stream.h>
|
||||
#include <proto/stick_table.h>
|
||||
#include <proto/stream_interface.h>
|
||||
@ -500,6 +500,11 @@ int tcp_connect_server(struct connection *conn, int data, int delack)
|
||||
setsockopt(fd, IPPROTO_TCP, TCP_QUICKACK, &zero, sizeof(zero));
|
||||
#endif
|
||||
|
||||
#ifdef TCP_USER_TIMEOUT
|
||||
/* there is not much more we can do here when it fails, it's still minor */
|
||||
if (srv && srv->tcp_ut)
|
||||
setsockopt(fd, IPPROTO_TCP, TCP_USER_TIMEOUT, &srv->tcp_ut, sizeof(srv->tcp_ut));
|
||||
#endif
|
||||
if (global.tune.server_sndbuf)
|
||||
setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &global.tune.server_sndbuf, sizeof(global.tune.server_sndbuf));
|
||||
|
||||
@ -2310,6 +2315,31 @@ static int bind_parse_namespace(char **args, int cur_arg, struct proxy *px, stru
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TCP_USER_TIMEOUT
|
||||
/* parse the "tcp-ut" server keyword */
|
||||
static int srv_parse_tcp_ut(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
|
||||
{
|
||||
const char *ptr = NULL;
|
||||
unsigned int timeout;
|
||||
|
||||
if (!*args[*cur_arg + 1]) {
|
||||
memprintf(err, "'%s' : missing TCP User Timeout value", args[*cur_arg]);
|
||||
return ERR_ALERT | ERR_FATAL;
|
||||
}
|
||||
|
||||
ptr = parse_time_err(args[*cur_arg + 1], &timeout, TIME_UNIT_MS);
|
||||
if (ptr) {
|
||||
memprintf(err, "'%s' : expects a positive delay in milliseconds", args[*cur_arg]);
|
||||
return ERR_ALERT | ERR_FATAL;
|
||||
}
|
||||
|
||||
if (newsrv->addr.ss_family == AF_INET || newsrv->addr.ss_family == AF_INET6)
|
||||
newsrv->tcp_ut = timeout;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct cfg_kw_list cfg_kws = {ILH, {
|
||||
{ CFG_LISTEN, "tcp-request", tcp_parse_tcp_req },
|
||||
{ CFG_LISTEN, "tcp-response", tcp_parse_tcp_rep },
|
||||
@ -2385,6 +2415,12 @@ static struct bind_kw_list bind_kws = { "TCP", { }, {
|
||||
{ NULL, NULL, 0 },
|
||||
}};
|
||||
|
||||
static struct srv_kw_list srv_kws = { "TCP", { }, {
|
||||
#ifdef TCP_USER_TIMEOUT
|
||||
{ "tcp-ut", srv_parse_tcp_ut, 1, 0 }, /* set TCP user timeout on server */
|
||||
#endif
|
||||
{ NULL, NULL, 0 },
|
||||
}};
|
||||
|
||||
static struct action_kw_list tcp_req_conn_actions = {ILH, {
|
||||
{ "silent-drop", tcp_parse_silent_drop },
|
||||
@ -2421,6 +2457,7 @@ static void __tcp_protocol_init(void)
|
||||
cfg_register_keywords(&cfg_kws);
|
||||
acl_register_keywords(&acl_kws);
|
||||
bind_register_keywords(&bind_kws);
|
||||
srv_register_keywords(&srv_kws);
|
||||
tcp_req_conn_keywords_register(&tcp_req_conn_actions);
|
||||
tcp_req_cont_keywords_register(&tcp_req_cont_actions);
|
||||
tcp_res_cont_keywords_register(&tcp_res_cont_actions);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user