From: Nick Porter Date: Fri, 28 Jun 2024 11:20:50 +0000 (+0100) Subject: Set a capacity for trunk backlog X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1d3082f2c0934933e1577bfb1d8b5ab05889c124;p=thirdparty%2Ffreeradius-server.git Set a capacity for trunk backlog 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. --- diff --git a/src/lib/server/trunk.c b/src/lib/server/trunk.c index 6707a471660..7136d77e7b0 100644 --- a/src/lib/server/trunk.c +++ b/src/lib/server/trunk.c @@ -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; } } diff --git a/src/lib/server/trunk.h b/src/lib/server/trunk.h index a38609dbcec..6c6db3e6698 100644 --- a/src/lib/server/trunk.h +++ b/src/lib/server/trunk.h @@ -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.