From 86034318226029458c51d26a06e96e084e402f72 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Fri, 29 Dec 2006 00:10:33 +0100 Subject: [PATCH] [MEDIUM] split fe->maxconn into fe->maxconn and be->fullconn The maxconn argument is used only for the listeners, and the fullconn is used only for the backends. If unset, it inherits maxconn's value which itself can inherit the default or the global value (we might need to change this). --- include/types/proxy.h | 3 ++- src/cfgparse.c | 24 ++++++++++++++++++++++-- src/queue.c | 17 ++++++++++++----- 3 files changed, 36 insertions(+), 8 deletions(-) diff --git a/include/types/proxy.h b/include/types/proxy.h index 848014335..8aaa3a773 100644 --- a/include/types/proxy.h +++ b/include/types/proxy.h @@ -98,7 +98,8 @@ struct proxy { unsigned int feconn, feconn_max; /* # of active frontend sessions */ unsigned int beconn, beconn_max; /* # of active backend sessions */ unsigned int cum_feconn, cum_beconn; /* cumulated number of processed sessions */ - unsigned int maxconn; /* max # of active sessions */ + unsigned int maxconn; /* max # of active sessions on the frontend */ + unsigned int fullconn; /* #conns on backend above which servers are used at full load */ unsigned failed_conns, failed_resp; /* failed connect() and responses */ unsigned failed_secu; /* blocked responses because of security concerns */ int conn_retries; /* maximum number of connect retries */ diff --git a/src/cfgparse.c b/src/cfgparse.c index d70768592..42e250b2f 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -395,6 +395,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args) /* set default values */ curproxy->state = defproxy.state; curproxy->maxconn = defproxy.maxconn; + curproxy->fullconn = defproxy.fullconn; curproxy->conn_retries = defproxy.conn_retries; curproxy->options = defproxy.options; @@ -909,6 +910,13 @@ int cfg_parse_listen(const char *file, int linenum, char **args) } curproxy->maxconn = atol(args[1]); } + else if (!strcmp(args[0], "fullconn")) { /* fullconn */ + if (*(args[1]) == 0) { + Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]); + return -1; + } + curproxy->fullconn = atol(args[1]); + } else if (!strcmp(args[0], "grace")) { /* grace time (ms) */ if (*(args[1]) == 0) { Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]); @@ -1973,6 +1981,13 @@ int readcfgfile(const char *file) memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt)); } + /* for backwards compatibility with "listen" instances, if + * fullconn is not set but maxconn is set, then maxconn + * is used. + */ + if (!curproxy->fullconn) + curproxy->fullconn = curproxy->maxconn; + /* first, we will invert the servers list order */ newsrv = NULL; while (curproxy->srv) { @@ -2035,13 +2050,18 @@ int readcfgfile(const char *file) */ newsrv = curproxy->srv; while (newsrv != NULL) { - if (newsrv->minconn >= newsrv->maxconn) { + if (newsrv->minconn > newsrv->maxconn) { /* Only 'minconn' was specified, or it was higher than or equal * to 'maxconn'. Let's turn this into maxconn and clean it, as * this will avoid further useless expensive computations. */ newsrv->maxconn = newsrv->minconn; - newsrv->minconn = 0; + } else if (newsrv->maxconn && !newsrv->minconn) { + /* minconn was not specified, so we set it to maxconn */ + newsrv->minconn = newsrv->maxconn; + } else if (!curproxy->fullconn) { + Alert("parsing [%s:%d] : fullconn is mandatory when minconn is set on a server.\n", file, linenum); + return -1; } if (newsrv->maxconn > 0) { diff --git a/src/queue.c b/src/queue.c index 8f0474cb8..611cfe95c 100644 --- a/src/queue.c +++ b/src/queue.c @@ -25,14 +25,21 @@ void **pool_pendconn = NULL; /* returns the effective dynamic maxconn for a server, considering the minconn - * and the proxy's usage relative to its saturation. + * and the proxy's usage relative to its dynamic connections limit. It is + * expected that 0 < s->minconn <= s->maxconn when this is called. */ unsigned int srv_dynamic_maxconn(const struct server *s) { - return (s->proxy->beconn >= s->proxy->maxconn) ? s->maxconn : - (s->minconn ? - MAX(s->maxconn * s->proxy->beconn / s->proxy->maxconn, s->minconn) - : s->maxconn); + if (s->proxy->beconn >= s->proxy->fullconn) + /* no fullconn or proxy is full */ + return s->maxconn; + + if (s->minconn == s->maxconn) + /* static limit */ + return s->maxconn; + + return MAX(s->minconn, + s->proxy->beconn * s->maxconn / s->proxy->fullconn); }