mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-11-29 14:50:59 +01:00
OPTIM/MINOR: config: Optimize fullconn automatic computation loading configuration
The previous version used an O(number of proxies)^2 algo to get the sum of the number of maxconns of frontends which reference a backend at least once. This new version adds the frontend's maxconn number to the backend's struct proxy member 'tot_fe_maxconn' when the backend name is resolved for switching rules or default_backend statment. At the end, the final backend's fullconn is computed looping only one time for all on proxies O(n). The load of a configuration using a large amount of backends (10 thousands) without configured fullconn was reduced from several minutes to few seconds.
This commit is contained in:
parent
3eb5b3fdd3
commit
3f78357066
@ -326,6 +326,7 @@ struct proxy {
|
|||||||
struct freq_ctr be_sess_per_sec; /* sessions per second on the backend */
|
struct freq_ctr be_sess_per_sec; /* sessions per second on the backend */
|
||||||
unsigned int fe_sps_lim; /* limit on new sessions per second on the frontend */
|
unsigned int fe_sps_lim; /* limit on new sessions per second on the frontend */
|
||||||
unsigned int fullconn; /* #conns on backend above which servers are used at full load */
|
unsigned int fullconn; /* #conns on backend above which servers are used at full load */
|
||||||
|
unsigned int tot_fe_maxconn; /* #maxconn of frontends linked to that backend, it is used to compute fullconn */
|
||||||
struct in_addr except_net, except_mask; /* don't x-forward-for for this address. FIXME: should support IPv6 */
|
struct in_addr except_net, except_mask; /* don't x-forward-for for this address. FIXME: should support IPv6 */
|
||||||
struct in_addr except_to; /* don't x-original-to for this address. */
|
struct in_addr except_to; /* don't x-original-to for this address. */
|
||||||
struct in_addr except_mask_to; /* the netmask for except_to. */
|
struct in_addr except_mask_to; /* the netmask for except_to. */
|
||||||
|
|||||||
@ -7542,7 +7542,8 @@ int check_config_validity()
|
|||||||
} else {
|
} else {
|
||||||
free(curproxy->defbe.name);
|
free(curproxy->defbe.name);
|
||||||
curproxy->defbe.be = target;
|
curproxy->defbe.be = target;
|
||||||
|
/* Update tot_fe_maxconn for a further fullconn's computation */
|
||||||
|
target->tot_fe_maxconn += curproxy->maxconn;
|
||||||
/* Emit a warning if this proxy also has some servers */
|
/* Emit a warning if this proxy also has some servers */
|
||||||
if (curproxy->srv) {
|
if (curproxy->srv) {
|
||||||
Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
|
Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
|
||||||
@ -7552,6 +7553,14 @@ int check_config_validity()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!curproxy->defbe.be && (curproxy->cap & PR_CAP_LISTEN) == PR_CAP_LISTEN) {
|
||||||
|
/* Case of listen without default backend
|
||||||
|
* The curproxy will be its own default backend
|
||||||
|
* so we update tot_fe_maxconn for a further
|
||||||
|
* fullconn's computation */
|
||||||
|
curproxy->tot_fe_maxconn += curproxy->maxconn;
|
||||||
|
}
|
||||||
|
|
||||||
/* find the target proxy for 'use_backend' rules */
|
/* find the target proxy for 'use_backend' rules */
|
||||||
list_for_each_entry(rule, &curproxy->switching_rules, list) {
|
list_for_each_entry(rule, &curproxy->switching_rules, list) {
|
||||||
struct proxy *target;
|
struct proxy *target;
|
||||||
@ -7613,6 +7622,23 @@ int check_config_validity()
|
|||||||
} else {
|
} else {
|
||||||
free((void *)rule->be.name);
|
free((void *)rule->be.name);
|
||||||
rule->be.backend = target;
|
rule->be.backend = target;
|
||||||
|
/* For each target of switching rules, we update
|
||||||
|
* their tot_fe_maxconn, except if a previous rule point
|
||||||
|
* on the same backend or on the default backend */
|
||||||
|
if (rule->be.backend != curproxy->defbe.be) {
|
||||||
|
struct switching_rule *swrule;
|
||||||
|
|
||||||
|
list_for_each_entry(swrule, &curproxy->switching_rules, list) {
|
||||||
|
if (rule == swrule) {
|
||||||
|
target->tot_fe_maxconn += curproxy->maxconn;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (!swrule->dynamic && swrule->be.backend == rule->be.backend) {
|
||||||
|
/* there is multiple ref of this backend */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -8869,48 +8895,11 @@ out_uri_auth_compat:
|
|||||||
* the possible incoming frontend's maxconns.
|
* the possible incoming frontend's maxconns.
|
||||||
*/
|
*/
|
||||||
if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
|
if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
|
||||||
struct proxy *fe;
|
|
||||||
int total = 0;
|
|
||||||
|
|
||||||
/* sum up the number of maxconns of frontends which
|
|
||||||
* reference this backend at least once or which are
|
|
||||||
* the same one ('listen').
|
|
||||||
*/
|
|
||||||
for (fe = proxy; fe; fe = fe->next) {
|
|
||||||
struct switching_rule *rule;
|
|
||||||
int found = 0;
|
|
||||||
|
|
||||||
if (!(fe->cap & PR_CAP_FE))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (fe == curproxy) /* we're on a "listen" instance */
|
|
||||||
found = 1;
|
|
||||||
|
|
||||||
if (fe->defbe.be == curproxy) /* "default_backend" */
|
|
||||||
found = 1;
|
|
||||||
|
|
||||||
/* check if a "use_backend" rule matches */
|
|
||||||
if (!found) {
|
|
||||||
list_for_each_entry(rule, &fe->switching_rules, list) {
|
|
||||||
if (!rule->dynamic && rule->be.backend == curproxy) {
|
|
||||||
found = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* now we've checked all possible ways to reference a backend
|
|
||||||
* from a frontend.
|
|
||||||
*/
|
|
||||||
if (!found)
|
|
||||||
continue;
|
|
||||||
total += fe->maxconn;
|
|
||||||
}
|
|
||||||
/* we have the sum of the maxconns in <total>. We only
|
/* we have the sum of the maxconns in <total>. We only
|
||||||
* keep 10% of that sum to set the default fullconn, with
|
* keep 10% of that sum to set the default fullconn, with
|
||||||
* a hard minimum of 1 (to avoid a divide by zero).
|
* a hard minimum of 1 (to avoid a divide by zero).
|
||||||
*/
|
*/
|
||||||
curproxy->fullconn = (total + 9) / 10;
|
curproxy->fullconn = (curproxy->tot_fe_maxconn + 9) / 10;
|
||||||
if (!curproxy->fullconn)
|
if (!curproxy->fullconn)
|
||||||
curproxy->fullconn = 1;
|
curproxy->fullconn = 1;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user