Skip to content

Commit dbe31e3

Browse files
committed
MEDIUM: session: account on server idle conns attached to session
This patch adds a new member <curr_sess_idle_conns> on the server. It serves as a counter of idle connections attached on a session instead of regular idle/safe trees. This is used only for private connections. The objective is to provide a method to detect if there is idle connections still referencing a server. This will be particularly useful to ensure that a server is removable. Currently, this is not yet necessary as idle connections are directly freed via "del server" handler under thread isolation. However, this procedure will be replaced by an asynchronous mechanism outside of thread isolation. Careful: connections attached to a session but not idle will not be accounted by this counter. These connections can still be detected via srv_has_streams() so "del server" will be safe. This counter is maintain during the whole lifetime of a private connection. This is mandatory to guarantee "del server" safety and is conform with other idle server counters. What this means it that decrement is performed only when the connection transitions from idle to in use, or just prior to its deletion. For the first case, this is covered by session_get_conn(). The second case is trickier. It cannot be done via session_unown_conn() as a private connection may still live a little longer after its removal from session, most notably when scheduled for idle purging. Thus, conn_free() has been adjusted to handle the final decrement. Now, conn_backend_deinit() is also called for private connections if CO_FL_SESS_IDLE flag is present. This results in a call to srv_release_conn() which is responsible to decrement server idle counters.
1 parent 7a6e3c1 commit dbe31e3

File tree

4 files changed

+18
-5
lines changed

4 files changed

+18
-5
lines changed

include/haproxy/server-t.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,7 @@ struct server {
388388
unsigned int curr_total_conns; /* Current number of total connections to the server, used or idle, only calculated if strict-maxconn is used */
389389
unsigned int max_used_conns; /* Max number of used connections (the counter is reset at each connection purges */
390390
unsigned int est_need_conns; /* Estimate on the number of needed connections (max of curr and previous max_used) */
391+
unsigned int curr_sess_idle_conns; /* Current number of idle connections attached to a session instead of idle/safe trees. */
391392

392393
/* Element below are usd by LB algorithms and must be doable in
393394
* parallel to other threads reusing connections above.

src/connection.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -540,10 +540,9 @@ static void conn_backend_deinit(struct connection *conn)
540540
if (obj_type(conn->target) == OBJ_TYPE_SERVER) {
541541
struct server *srv = __objt_server(conn->target);
542542

543-
/* If the connection is not private, it is accounted by the server. */
544-
if (!(conn->flags & CO_FL_PRIVATE)) {
543+
if (!(conn->flags & CO_FL_PRIVATE) || (conn->flags & CO_FL_SESS_IDLE))
545544
srv_release_conn(srv, conn);
546-
}
545+
547546
if (srv->flags & SRV_F_STRICT_MAXCONN)
548547
_HA_ATOMIC_DEC(&srv->curr_total_conns);
549548
}

src/server.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7251,7 +7251,11 @@ static void srv_cleanup_connections(struct server *srv)
72517251
/* removes an idle conn after updating the server idle conns counters */
72527252
void srv_release_conn(struct server *srv, struct connection *conn)
72537253
{
7254-
if (conn->flags & CO_FL_LIST_MASK) {
7254+
if (conn->flags & CO_FL_SESS_IDLE) {
7255+
_HA_ATOMIC_DEC(&srv->curr_sess_idle_conns);
7256+
conn->flags &= ~CO_FL_SESS_IDLE;
7257+
}
7258+
else if (conn->flags & CO_FL_LIST_MASK) {
72557259
/* The connection is currently in the server's idle list, so tell it
72567260
* there's one less connection available in that list.
72577261
*/

src/session.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,6 @@ void session_free(struct session *sess)
139139
list_for_each_entry_safe(conn, conn_back, &pconns->conn_list, sess_el) {
140140
LIST_DEL_INIT(&conn->sess_el);
141141
conn->owner = NULL;
142-
conn->flags &= ~CO_FL_SESS_IDLE;
143142
LIST_APPEND(&conn_tmp_list, &conn->sess_el);
144143
}
145144
MT_LIST_DELETE(&pconns->srv_el);
@@ -732,6 +731,9 @@ int session_reinsert_idle_conn(struct session *sess, struct connection *conn)
732731
/* Check that session <sess> is able to keep idle connection <conn>. This must
733732
* be called each time a connection stored in a session becomes idle.
734733
*
734+
* If <conn> can be kept as idle in the session, idle sess conn counter of its
735+
* target server will be incremented.
736+
*
735737
* Returns 0 if the connection is kept, else non-zero if the connection was
736738
* explicitely removed from session.
737739
*/
@@ -758,6 +760,8 @@ int session_check_idle_conn(struct session *sess, struct connection *conn)
758760
else {
759761
conn->flags |= CO_FL_SESS_IDLE;
760762
sess->idle_conns++;
763+
if (srv)
764+
HA_ATOMIC_INC(&srv->curr_sess_idle_conns);
761765
}
762766

763767
return 0;
@@ -771,6 +775,7 @@ struct connection *session_get_conn(struct session *sess, void *target, int64_t
771775
{
772776
struct connection *srv_conn, *res = NULL;
773777
struct sess_priv_conns *pconns;
778+
struct server *srv;
774779

775780
HA_SPIN_LOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock);
776781

@@ -787,6 +792,10 @@ struct connection *session_get_conn(struct session *sess, void *target, int64_t
787792
if (srv_conn->flags & CO_FL_SESS_IDLE) {
788793
srv_conn->flags &= ~CO_FL_SESS_IDLE;
789794
sess->idle_conns--;
795+
796+
srv = objt_server(srv_conn->target);
797+
if (srv)
798+
HA_ATOMIC_DEC(&srv->curr_sess_idle_conns);
790799
}
791800

792801
res = srv_conn;

0 commit comments

Comments
 (0)