From f131481a0af79037bc6616edf450ae81d80084d7 Mon Sep 17 00:00:00 2001 From: Olivier Houchard Date: Mon, 18 Feb 2019 16:41:17 +0100 Subject: [PATCH] BUG/MEDIUM: servers: Add a per-thread counter of idle connections. Add a per-thread counter of idling connections, and use it to determine how many connections we should kill after the timeout, instead of using the global counter, or we're likely to just kill most of the connections. This should be backported to 1.9. --- include/proto/connection.h | 1 + include/proto/server.h | 1 + include/types/server.h | 1 + src/backend.c | 1 + src/cfgparse.c | 3 +++ src/haproxy.c | 1 + src/server.c | 2 +- 7 files changed, 9 insertions(+), 1 deletion(-) diff --git a/include/proto/connection.h b/include/proto/connection.h index 1dc0512f4..45b8a8a53 100644 --- a/include/proto/connection.h +++ b/include/proto/connection.h @@ -694,6 +694,7 @@ static inline void conn_free(struct connection *conn) if (conn->idle_time > 0) { struct server *srv = __objt_server(conn->target); HA_ATOMIC_SUB(&srv->curr_idle_conns, 1); + srv->curr_idle_thr[tid]--; } conn_force_unsubscribe(conn); diff --git a/include/proto/server.h b/include/proto/server.h index 51d1015e9..9467f697a 100644 --- a/include/proto/server.h +++ b/include/proto/server.h @@ -253,6 +253,7 @@ static inline int srv_add_to_idle_list(struct server *srv, struct connection *co } LIST_DEL(&conn->list); LIST_ADDQ(&srv->idle_orphan_conns[tid], &conn->list); + srv->curr_idle_thr[tid]++; conn->idle_time = now_ms; if (!(task_in_wq(srv->idle_task[tid])) && diff --git a/include/types/server.h b/include/types/server.h index e4371af00..eae7d450d 100644 --- a/include/types/server.h +++ b/include/types/server.h @@ -225,6 +225,7 @@ struct server { unsigned int pool_purge_delay; /* Delay before starting to purge the idle conns pool */ unsigned int max_idle_conns; /* Max number of connection allowed in the orphan connections list */ unsigned int curr_idle_conns; /* Current number of orphan idling connections */ + unsigned int *curr_idle_thr; /* Current number of orphan idling connections per thread */ int max_reuse; /* Max number of requests on a same connection */ struct task **idle_task; /* task responsible for cleaning idle orphan connections */ struct task *warmup; /* the task dedicated to the warmup when slowstart is set */ diff --git a/src/backend.c b/src/backend.c index 3c752a273..d15020aa6 100644 --- a/src/backend.c +++ b/src/backend.c @@ -1344,6 +1344,7 @@ int connect_server(struct stream *s) LIST_DEL(&srv_conn->list); srv_conn->idle_time = 0; HA_ATOMIC_SUB(&srv->curr_idle_conns, 1); + srv->curr_idle_thr[tid]--; LIST_ADDQ(&srv->idle_conns[tid], &srv_conn->list); if (LIST_ISEMPTY(&srv->idle_orphan_conns[tid])) task_unlink_wq(srv->idle_task[tid]); diff --git a/src/cfgparse.c b/src/cfgparse.c index 59ba77376..fde3097e8 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -3593,6 +3593,9 @@ out_uri_auth_compat: newsrv->idle_task[i]->process = srv_cleanup_idle_connections; newsrv->idle_task[i]->context = newsrv; } + newsrv->curr_idle_thr = calloc(global.nbthread, sizeof(int)); + if (!newsrv->curr_idle_thr) + goto err; continue; err: ha_alert("parsing [%s:%d] : failed to allocate idle connection tasks for server '%s'.\n", diff --git a/src/haproxy.c b/src/haproxy.c index 7c434b361..50133fb1e 100644 --- a/src/haproxy.c +++ b/src/haproxy.c @@ -2436,6 +2436,7 @@ void deinit(void) free(s->priv_conns); free(s->safe_conns); free(s->idle_orphan_conns); + free(s->curr_idle_thr); if (s->idle_task) { int i; diff --git a/src/server.c b/src/server.c index 312aa1994..4068255e5 100644 --- a/src/server.c +++ b/src/server.c @@ -5309,7 +5309,7 @@ struct task *srv_cleanup_idle_connections(struct task *task, void *context, unsi { struct server *srv = context; struct connection *conn, *conn_back; - unsigned int to_destroy = srv->curr_idle_conns / 2 + (srv->curr_idle_conns & 1); + unsigned int to_destroy = srv->curr_idle_thr[tid] / 2 + (srv->curr_idle_thr[tid] & 1); unsigned int i = 0;