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 */
/* 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;
}
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]);
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) {
*/
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) {
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);
}