BUG/MAJOR: connection: fix server used_conns with H2 + reuse safe

By default, backend connections are accounted by the server. This allows
to determine the number of idle connections to keep. A backend
connection can also be marked as private to prevent its reuse. It is
thus removed from server lists into the session list. As such, a private
connection is not accounted into server : conn_set_private() uses
srv_release_conn() to ensure this.

When using HTTP/2 on backend side with default http-reuse safe, the
above principle are mixed. Indeed, when a connection is first used, or
switches from idle to used, it is moved into the session list but it is
not flagged as private. This is done to prevent its sharing by different
clients to prevent head-of-line blocking issue. When all streams are
closed, the connection becomes idle again and is reinserted in the
server list. This has been introduced by the following patch :

  0d21deaded1a4bbd1e1700ab8386af1f1441ea73
  MEDIUM: backend: add reused conn to sess if mux marked as HOL blocking

When freeing a backend connection, special care is taken to ensure
server used counter is decremented. This is implemented into
conn_backend_deinit(). However, this function does this only if the
connection is not present in a session list. This is valid for private
connections. However, if a connection is non-private and present only
temporarily into a session list, the decrement operation won't be
executed despite the connection being accounted by the server.

This bug has several impacts. The server used counter won't be able to
reach its initial null value, even when all its connections are closed.
This can result in a wrong estimation of necessary idle connections,
which may cause unnecessary new connection usage. Also, this will
prevent definitely the server from being removed via "delete server" CLI
command.

This should be backported up to 2.4. Note that conn_backend_deinit() was
introduced in 2.9. For lesser versions, the change should be done
directly into conn_free().
This commit is contained in:
Amaury Denoyelle 2024-03-19 10:34:45 +01:00
parent fd3ce173aa
commit 87b96cf3a5

View File

@ -511,12 +511,12 @@ static int conn_backend_init(struct connection *conn)
*/ */
static void conn_backend_deinit(struct connection *conn) static void conn_backend_deinit(struct connection *conn)
{ {
/* If the connection is owned by the session, remove it from its list /* If the connection is owned by the session, remove it from its list. */
*/ if (LIST_INLIST(&conn->sess_el))
if (conn_is_back(conn) && LIST_INLIST(&conn->sess_el)) {
session_unown_conn(conn->owner, conn); session_unown_conn(conn->owner, conn);
}
else if (!(conn->flags & CO_FL_PRIVATE)) { /* If the connection is not private, it is accounted by the server. */
if (!(conn->flags & CO_FL_PRIVATE)) {
if (obj_type(conn->target) == OBJ_TYPE_SERVER) if (obj_type(conn->target) == OBJ_TYPE_SERVER)
srv_release_conn(__objt_server(conn->target), conn); srv_release_conn(__objt_server(conn->target), conn);
} }