diff --git a/doc/configuration.txt b/doc/configuration.txt index 85b687eb6..3e49d0e98 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -5481,7 +5481,8 @@ maxconn are not sized to accept such loads, and for this reason it is generally wise to assign them some reasonable connection limits. - By default, this value is set to 2000. + When this value is set to zero, which is the default, the global "maxconn" + value is used. See also : "server", global section's "maxconn", "fullconn" diff --git a/include/proto/proxy.h b/include/proto/proxy.h index 782372efc..7bd942109 100644 --- a/include/proto/proxy.h +++ b/include/proto/proxy.h @@ -68,6 +68,7 @@ void proxy_capture_error(struct proxy *proxy, int is_back, unsigned int buf_out, unsigned int err_pos, const union error_snapshot_ctx *ctx, void (*show)(struct buffer *, const struct error_snapshot *)); +void proxy_adjust_all_maxconn(); struct proxy *cli_find_frontend(struct appctx *appctx, const char *arg); struct proxy *cli_find_frontend(struct appctx *appctx, const char *arg); diff --git a/src/cfgparse.c b/src/cfgparse.c index e29ab9764..1a03d97ec 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -125,7 +125,7 @@ struct list postparsers = LIST_HEAD_INIT(postparsers); char *cursection = NULL; struct proxy defproxy = { }; /* fake proxy used to assign default values on all instances */ -int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */ +int cfg_maxpconn = 0; /* # of simultaneous connections per proxy (-N) */ int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */ char *cfg_scope = NULL; /* the current scope during the configuration parsing */ @@ -2524,8 +2524,6 @@ int check_config_validity() } else { free(curproxy->defbe.name); 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 */ if (curproxy->srv) { ha_warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n", @@ -2535,14 +2533,6 @@ 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 */ list_for_each_entry(rule, &curproxy->switching_rules, list) { struct proxy *target; @@ -2611,23 +2601,6 @@ int check_config_validity() } else { free((void *)rule->be.name); 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; - } - } - } } } @@ -3817,24 +3790,6 @@ int check_config_validity() } } - /* automatically compute fullconn if not set. We must not do it in the - * loop above because cross-references are not yet fully resolved. - */ - for (curproxy = proxies_list; curproxy; curproxy = curproxy->next) { - /* If is not set, let's set it to 10% of the sum of - * the possible incoming frontend's maxconns. - */ - if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) { - /* we have the sum of the maxconns in . We only - * keep 10% of that sum to set the default fullconn, with - * a hard minimum of 1 (to avoid a divide by zero). - */ - curproxy->fullconn = (curproxy->tot_fe_maxconn + 9) / 10; - if (!curproxy->fullconn) - curproxy->fullconn = 1; - } - } - /* * Recount currently required checks. */ diff --git a/src/haproxy.c b/src/haproxy.c index 942c07597..59da1fda6 100644 --- a/src/haproxy.c +++ b/src/haproxy.c @@ -2069,6 +2069,8 @@ static void init(int argc, char **argv) global.maxsock += p->peers_fe->maxconn; } + proxy_adjust_all_maxconn(); + if (global.tune.maxpollevents <= 0) global.tune.maxpollevents = MAX_POLL_EVENTS; diff --git a/src/proxy.c b/src/proxy.c index 7f442b9da..e60b34a21 100644 --- a/src/proxy.c +++ b/src/proxy.c @@ -1488,6 +1488,75 @@ void proxy_capture_error(struct proxy *proxy, int is_back, HA_SPIN_UNLOCK(PROXY_LOCK, &proxy->lock); } +/* Configure all proxies which lack a maxconn setting to use the global one by + * default. This avoids the common mistake consisting in setting maxconn only + * in the global section and discovering the hard way that it doesn't propagate + * through the frontends. These values are also propagated through the various + * targetted backends, whose fullconn is finally calculated if not yet set. + */ +void proxy_adjust_all_maxconn() +{ + struct proxy *curproxy; + struct switching_rule *swrule1, *swrule2; + + for (curproxy = proxies_list; curproxy; curproxy = curproxy->next) { + if (curproxy->state == PR_STSTOPPED) + continue; + + if (!(curproxy->cap & PR_CAP_FE)) + continue; + + if (!curproxy->maxconn) + curproxy->maxconn = global.maxconn; + + /* update the target backend's fullconn count : default_backend */ + if (curproxy->defbe.be) + curproxy->defbe.be->tot_fe_maxconn += curproxy->maxconn; + else if ((curproxy->cap & PR_CAP_LISTEN) == PR_CAP_LISTEN) + curproxy->tot_fe_maxconn += curproxy->maxconn; + + list_for_each_entry(swrule1, &curproxy->switching_rules, list) { + /* For each target of switching rules, we update their + * tot_fe_maxconn, except if a previous rule points to + * the same backend or to the default backend. + */ + if (swrule1->be.backend != curproxy->defbe.be) { + list_for_each_entry(swrule2, &curproxy->switching_rules, list) { + if (swrule2 == swrule1) { + swrule1->be.backend->tot_fe_maxconn += curproxy->maxconn; + break; + } + else if (!swrule2->dynamic && swrule2->be.backend == swrule1->be.backend) { + /* there are multiple refs of this backend */ + break; + } + } + } + } + } + + /* automatically compute fullconn if not set. We must not do it in the + * loop above because cross-references are not yet fully resolved. + */ + for (curproxy = proxies_list; curproxy; curproxy = curproxy->next) { + if (curproxy->state == PR_STSTOPPED) + continue; + + /* If is not set, let's set it to 10% of the sum of + * the possible incoming frontend's maxconns. + */ + if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) { + /* we have the sum of the maxconns in . We only + * keep 10% of that sum to set the default fullconn, with + * a hard minimum of 1 (to avoid a divide by zero). + */ + curproxy->fullconn = (curproxy->tot_fe_maxconn + 9) / 10; + if (!curproxy->fullconn) + curproxy->fullconn = 1; + } + } +} + /* Config keywords below */ static struct cfg_kw_list cfg_kws = {ILH, {