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.
This commit is contained in:
Olivier Houchard 2019-02-18 16:41:17 +01:00 committed by Willy Tarreau
parent e737103173
commit f131481a0a
7 changed files with 9 additions and 1 deletions

View File

@ -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);

View File

@ -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])) &&

View File

@ -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 */

View File

@ -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]);

View File

@ -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",

View File

@ -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;

View File

@ -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;