From 079cb9af22da65e528a14abbcc83c7d94206ccd9 Mon Sep 17 00:00:00 2001 From: Olivier Houchard Date: Mon, 30 Mar 2020 00:23:57 +0200 Subject: [PATCH] MEDIUM: connections: Revamp the way idle connections are killed The original algorithm always killed half the idle connections. This doesn't take into account the way the load can change. Instead, we now kill half of the exceeding connections (exceeding connection being the number of used + idle connections past the last maximum used connections reached). That way if we reach a peak, we will kill much less, and it'll slowly go back down when there's less usage. --- src/server.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/src/server.c b/src/server.c index 8d4ad89893..725a7c63e2 100644 --- a/src/server.c +++ b/src/server.c @@ -5590,6 +5590,9 @@ struct task *srv_cleanup_idle_connections(struct task *task, void *context, unsi HA_SPIN_LOCK(OTHER_LOCK, &idle_conn_srv_lock); while (1) { int srv_is_empty = 1; + int exceed_conns; + int to_kill; + int curr_idle; eb = eb32_lookup_ge(&idle_conn_srv, now_ms - TIMER_LOOK_BACK); if (!eb) { @@ -5609,12 +5612,27 @@ struct task *srv_cleanup_idle_connections(struct task *task, void *context, unsi break; } srv = eb32_entry(eb, struct server, idle_node); - for (i = 0; i < global.nbthread; i++) { - int max_conn = (srv->curr_idle_thr[i] / 2) + - (srv->curr_idle_thr[i] & 1); + + /* Calculate how many idle connections we want to kill : + * we want to remove half the difference between the total + * of established connections (used or idle) and the max + * number of used connections. + */ + curr_idle = srv->curr_idle_conns; + if (curr_idle == 0) + goto remove; + exceed_conns = srv->curr_used_conns + curr_idle - + srv->max_used_conns; + exceed_conns = to_kill = exceed_conns / 2 + (exceed_conns & 1); + srv->max_used_conns = srv->curr_used_conns; + + for (i = 0; i < global.nbthread && to_kill > 0; i++) { + int max_conn; int j; int did_remove = 0; + max_conn = (exceed_conns * srv->curr_idle_thr[i]) / + curr_idle + 1; HA_SPIN_LOCK(OTHER_LOCK, &toremove_lock[i]); for (j = 0; j < max_conn; j++) { struct connection *conn = MT_LIST_POP(&srv->idle_conns[i], struct connection *, list); @@ -5632,6 +5650,7 @@ struct task *srv_cleanup_idle_connections(struct task *task, void *context, unsi if (did_remove) task_wakeup(idle_conn_cleanup[i], TASK_WOKEN_OTHER); } +remove: eb32_delete(&srv->idle_node); if (!srv_is_empty) { /* There are still more idle connections, add the -- 2.39.5