]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Set a capacity for trunk backlog
authorNick Porter <nick@portercomputing.co.uk>
Fri, 28 Jun 2024 11:20:50 +0000 (12:20 +0100)
committerNick Porter <nick@portercomputing.co.uk>
Fri, 28 Jun 2024 16:11:39 +0000 (17:11 +0100)
And allow requests to be allocated / enqueued even if the max
connections and requests per connection limit is reached, up to the
backlog limit.

Helps handle spikes in traffic, particularly where trunks are limited to
one request per connection, and there are server side limitations on the
number of connections that can be made - e.g. SQL servers.

src/lib/server/trunk.c
src/lib/server/trunk.h

index 6707a471660d6291d92d8ad8fbea366f51bd8cc4..7136d77e7b0d330510c757cec41aafe0be528bbd 100644 (file)
@@ -322,6 +322,8 @@ conf_parser_t const trunk_config[] = {
 
        { FR_CONF_OFFSET("manage_interval", trunk_conf_t, manage_interval), .dflt = "0.2" },
 
+       { FR_CONF_OFFSET("max_backlog", trunk_conf_t, max_backlog), .dflt = "1000" },
+
        { FR_CONF_OFFSET_SUBSECTION("connection", 0, trunk_conf_t, conn_conf, trunk_config_connection), .subcs_size = sizeof(trunk_config_connection) },
        { FR_CONF_POINTER("request", 0, CONF_FLAG_SUBSECTION, NULL), .subcs = (void const *) trunk_config_request },
 
@@ -1642,12 +1644,13 @@ static trunk_enqueue_t trunk_request_check_enqueue(trunk_connection_t **tconn_ou
 
                        total_reqs = trunk_request_count_by_state(trunk, TRUNK_CONN_ALL,
                                                                     TRUNK_REQUEST_STATE_ALL);
-                       if (total_reqs >= limit) {
+                       if (total_reqs >= (limit + trunk->conf.max_backlog)) {
                                RATE_LIMIT_LOCAL_ROPTIONAL(&trunk->limit_max_requests_alloc_log,
                                                           RWARN, WARN, "Refusing to alloc requests - "
                                                           "Limit of %"PRIu64" (max = %u * per_connection_max = %u) "
-                                                          "requests reached",
-                                                          limit, trunk->conf.max, trunk->conf.max_req_per_conn);
+                                                          "plus %u backlog requests reached",
+                                                          limit, trunk->conf.max, trunk->conf.max_req_per_conn,
+                                                          trunk->conf.max_backlog);
                                return TRUNK_ENQUEUE_NO_CAPACITY;
                        }
                }
@@ -2468,12 +2471,13 @@ trunk_request_t *trunk_request_alloc(trunk_t *trunk, request_t *request)
                uint64_t limit;
 
                limit = (uint64_t) trunk->conf.max_req_per_conn * trunk->conf.max;
-               if (trunk->pub.req_alloc >= limit) {
+               if (trunk->pub.req_alloc >= (limit + trunk->conf.max_backlog)) {
                        RATE_LIMIT_LOCAL_ROPTIONAL(&trunk->limit_max_requests_alloc_log,
                                                   RWARN, WARN, "Refusing to alloc requests - "
                                                   "Limit of %"PRIu64" (max = %u * per_connection_max = %u) "
-                                                  "requests reached",
-                                                  limit, trunk->conf.max, trunk->conf.max_req_per_conn);
+                                                  "plus %u backlog requests reached",
+                                                  limit, trunk->conf.max, trunk->conf.max_req_per_conn,
+                                                  trunk->conf.max_backlog);
                        return NULL;
                }
        }
index a38609dbceca90eebc437af1f4ae51fdb9aaf87a..6c6db3e669811ced7b0519f100d878b317764681 100644 (file)
@@ -241,6 +241,8 @@ typedef struct {
                                                        ///< Used to determine if we need to create new connections
                                                        ///< and whether we can enqueue new requests.
 
+       uint32_t                max_backlog;            //!< Maximum number of requests that can be in the backlog.
+
        uint64_t                max_uses;               //!< The maximum time a connection can be used.
 
        fr_time_delta_t         lifetime;               //!< Time between reconnects.