Skip to content

Commit 7a6e3c1

Browse files
committed
MAJOR: server: implement purging of private idle connections
When a server goes into maintenance, or if its IP address is changed, idle connections attached to it are scheduled for deletion via the purge mechanism. Connections are moved from server idle/safe list to the purge list relative to their thread. Connections are freed on their owned thread by the scheduled purge task. This patch extends this procedure to also handle private idle connections stored in sessions instead of servers. This is possible thanks via <sess_conns> list server member. A call to the newly defined-function session_purge_conns() is performed on each list element. This moves private connections from their session to the purge list alongside other server idle connections. This change relies on the serie of previous commits which ensure that access to private idle connections is now thread-safe, with idle_conns lock usage and careful manipulation of private idle conns in input/output handlers. The main benefit of this patch is that now all idle connections targetting a server set in maintenance are removed. Previously, private connections would remain until their attach sessions were closed.
1 parent 17a1dac commit 7a6e3c1

File tree

3 files changed

+45
-0
lines changed

3 files changed

+45
-0
lines changed

include/haproxy/session.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ int session_check_idle_conn(struct session *sess, struct connection *conn);
4949
struct connection *session_get_conn(struct session *sess, void *target, int64_t hash);
5050
void session_unown_conn(struct session *sess, struct connection *conn);
5151
int session_detach_idle_conn(struct session *sess, struct connection *conn);
52+
int sess_conns_cleanup_all_idle(struct sess_priv_conns *sess_conns);
5253

5354
/* Remove the refcount from the session to the tracked counters, and clear the
5455
* pointer to ensure this is only performed once. The caller is responsible for

src/server.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7210,6 +7210,7 @@ static int srv_migrate_conns_to_remove(struct list *list, struct mt_list *toremo
72107210
*/
72117211
static void srv_cleanup_connections(struct server *srv)
72127212
{
7213+
struct sess_priv_conns *sess_conns;
72137214
int did_remove;
72147215
int i;
72157216

@@ -7221,8 +7222,23 @@ static void srv_cleanup_connections(struct server *srv)
72217222
for (i = tid;;) {
72227223
did_remove = 0;
72237224
HA_SPIN_LOCK(IDLE_CONNS_LOCK, &idle_conns[i].idle_conns_lock);
7225+
7226+
/* idle connections */
72247227
if (srv_migrate_conns_to_remove(&srv->per_thr[i].idle_conn_list, &idle_conns[i].toremove_conns, -1) > 0)
72257228
did_remove = 1;
7229+
7230+
/* session attached connections */
7231+
while ((sess_conns = MT_LIST_POP(&srv->per_thr[i].sess_conns, struct sess_priv_conns *, srv_el))) {
7232+
if (sess_conns_cleanup_all_idle(sess_conns)) {
7233+
did_remove = 1;
7234+
7235+
if (LIST_ISEMPTY(&sess_conns->conn_list)) {
7236+
LIST_DELETE(&sess_conns->sess_el);
7237+
pool_free(pool_head_sess_priv_conns, sess_conns);
7238+
}
7239+
}
7240+
}
7241+
72267242
HA_SPIN_UNLOCK(IDLE_CONNS_LOCK, &idle_conns[i].idle_conns_lock);
72277243
if (did_remove)
72287244
task_wakeup(idle_conns[i].cleanup_task, TASK_WOKEN_OTHER);

src/session.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -874,6 +874,34 @@ int session_detach_idle_conn(struct session *sess, struct connection *conn)
874874
return 1;
875875
}
876876

877+
/* Remove every idle backend connections stored in <sess_conns> and move them
878+
* into the purge list. If <sess_conns> is empty it is also removed from the
879+
* session and freed.
880+
*
881+
* Returns the number of connections moved to purge list.
882+
*/
883+
int sess_conns_cleanup_all_idle(struct sess_priv_conns *sess_conns)
884+
{
885+
struct connection *conn, *back;
886+
int conn_tid = sess_conns->tid;
887+
int i = 0;
888+
889+
list_for_each_entry_safe(conn, back, &sess_conns->conn_list, sess_el) {
890+
if (!(conn->flags & CO_FL_SESS_IDLE))
891+
continue;
892+
893+
/* Decrement session idle counter. */
894+
--((struct session *)conn->owner)->idle_conns;
895+
896+
LIST_DEL_INIT(&conn->sess_el);
897+
MT_LIST_APPEND(&idle_conns[conn_tid].toremove_conns,
898+
&conn->toremove_list);
899+
++i;
900+
}
901+
902+
return i;
903+
}
904+
877905

878906
/*
879907
* Local variables:

0 commit comments

Comments
 (0)