Merge branch 'minconn' into abort-close

This commit is contained in:
willy tarreau 2006-05-21 21:11:03 +02:00
commit 12e0212448
3 changed files with 69 additions and 12 deletions

View File

@ -30,7 +30,7 @@
and might cause little trouble to some very specific clients used to
close immediately after sending the request (no support for KA, which ones?)
- minconn : makes the server's maxconn dynamic, which will be computed as a
+ minconn : makes the server's maxconn dynamic, which will be computed as a
ratio of the proxy's sessions :
srv->effective_maxconn =
max(srv->maxconn * px->nbsess / px->maxconn, srv->minconn)

View File

@ -1216,6 +1216,41 @@ Example :
server web-backup1 192.168.2.1:80 cookie s4 check maxconn 200 backup
server web-excuse 192.168.3.1:80 check backup
This was so much efficient at reducing the server's response time that some
users wanted to use low values to improve their server's performance. However,
they were not able anymore to handle very large loads because it was not
possible anymore to saturate the servers. For this reason, version 1.2.14 has
brought dynamic limitation with the addition of the parameter 'minconn'. When
this parameter is set along with maxconn, it will enable dynamic limitation
based on the instance's load. The maximum number of concurrent sessions on a
server will be proportionnal to the number of sessions on the instance relative
to its maxconn. A minimum of <minconn> will be allowed whatever the load. This
will ensure that servers will perform at their best level under normal loads,
while still handling surges when needed. The dynamic limit is computed like
this :
srv.dyn_limit = max(srv.minconn, srv.maxconn * inst.sess / inst.maxconn)
Example :
---------
# be nice with P3 which only has 256 MB of RAM.
listen web_appl 0.0.0.0:80
maxconn 10000
mode http
cookie SERVERID insert nocache indirect
balance roundrobin
server pentium3-800 192.168.1.1:80 cookie s1 weight 8 minconn 10 maxconn 100 check
server opteron-2.0G 192.168.1.2:80 cookie s2 weight 20 minconn 30 maxconn 300 check
server opteron-2.4G 192.168.1.3:80 cookie s3 weight 24 minconn 30 maxconn 300 check
server web-backup1 192.168.2.1:80 cookie s4 check maxconn 200 backup
server web-excuse 192.168.3.1:80 check backup
In the example above, the server 'pentium3-800' will receive at most 100
simultaneous sessions when the proxy instance will reach 10000 sessions, and
will receive only 10 simultaneous sessions when the proxy will be under 1000
sessions.
Notes :
-------
- The requests will not stay indefinitely in the queue, they follow the
@ -1223,6 +1258,8 @@ Notes :
timeout because the server is saturated or because the queue is filled,
the session will expire with a 503 error.
- if only <minconn> is specified, it has the same effect as <maxconn>
- setting too low values for maxconn might improve performance but might also
allow slow users to block access to the server for other users.

View File

@ -587,7 +587,7 @@ struct server {
unsigned int wscore; /* weight score, used during srv map computation */
int cur_sess, cur_sess_max; /* number of currently active sessions (including syn_sent) */
unsigned int cum_sess; /* cumulated number of sessions really sent to this server */
unsigned int maxconn; /* max # of active sessions. 0 = unlimited. */
unsigned int maxconn, minconn; /* max # of active sessions (0 = unlimited), min# for dynamic limit. */
unsigned failed_checks, down_trans; /* failed checks and up-down transitions */
unsigned failed_conns, failed_resp; /* failed connect() and responses */
unsigned failed_secu; /* blocked responses because of security concerns */
@ -695,9 +695,9 @@ struct proxy {
struct list pendconns; /* pending connections with no server assigned yet */
int nbpend, nbpend_max; /* number of pending connections with no server assigned yet */
int totpend; /* total number of pending connections on this instance (for stats) */
int nbconn, nbconn_max; /* # of active sessions */
unsigned int nbconn, nbconn_max; /* # of active sessions */
unsigned int cum_conn; /* cumulated number of processed sessions */
int maxconn; /* max # of active sessions */
unsigned int maxconn; /* max # of active sessions */
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 */
@ -1983,12 +1983,22 @@ static struct pendconn *pendconn_add(struct session *sess) {
return p;
}
/* returns the effective dynamic maxconn for a server, considering the minconn
* and the proxy's usage relative to its saturation.
*/
static unsigned int srv_dynamic_maxconn(struct server *s) {
return s->minconn ?
((s->maxconn * s->proxy->nbconn / s->proxy->maxconn) < s->minconn) ? s->minconn :
(s->maxconn * s->proxy->nbconn / s->proxy->maxconn) : s->maxconn;
}
/* returns 0 if nothing has to be done for server <s> regarding queued connections,
* and non-zero otherwise. Suited for and if/else usage.
*/
static inline int may_dequeue_tasks(struct server *s, struct proxy *p) {
return (s && (s->nbpend || p->nbpend) &&
s->maxconn && s->cur_sess < s->maxconn && s->queue_mgt);
(!s->maxconn || s->cur_sess < srv_dynamic_maxconn(s)) &&
s->queue_mgt);
}
@ -2157,7 +2167,7 @@ static inline struct server *get_server_rr_with_conns(struct proxy *px) {
do {
srv = px->srv_map[newidx++];
if (!srv->maxconn || srv->cur_sess < srv->maxconn) {
if (!srv->maxconn || srv->cur_sess < srv_dynamic_maxconn(srv)) {
px->srv_rr_idx = newidx;
return srv;
}
@ -2349,7 +2359,7 @@ int assign_server_and_queue(struct session *s) {
* is not needed.
*/
if (s->srv &&
s->srv->maxconn && s->srv->cur_sess >= s->srv->maxconn) {
s->srv->maxconn && s->srv->cur_sess >= srv_dynamic_maxconn(s->srv)) {
p = pendconn_add(s);
if (p)
return SRV_STATUS_QUEUED;
@ -2364,8 +2374,8 @@ int assign_server_and_queue(struct session *s) {
switch (err) {
case SRV_STATUS_OK:
/* in balance mode, we might have servers with connection limits */
if (s->srv != NULL &&
s->srv->maxconn && s->srv->cur_sess >= s->srv->maxconn) {
if (s->srv &&
s->srv->maxconn && s->srv->cur_sess >= srv_dynamic_maxconn(s->srv)) {
p = pendconn_add(s);
if (p)
return SRV_STATUS_QUEUED;
@ -6737,7 +6747,7 @@ int process_chk(struct task *t) {
/* check if we can handle some connections queued at the proxy. We
* will take as many as we can handle.
*/
for (xferred = 0; !s->maxconn || xferred < s->maxconn; xferred++) {
for (xferred = 0; !s->maxconn || xferred < srv_dynamic_maxconn(s); xferred++) {
struct session *sess;
struct pendconn *p;
@ -6810,7 +6820,7 @@ int process_srv_queue(struct task *t) {
/* First, check if we can handle some connections queued at the proxy. We
* will take as many as we can handle.
*/
for (xferred = 0; s->cur_sess + xferred < s->maxconn; xferred++) {
for (xferred = 0; s->cur_sess + xferred < srv_dynamic_maxconn(s); xferred++) {
struct session *sess;
sess = pendconn_get_next_sess(s, p);
@ -8556,6 +8566,10 @@ int cfg_parse_listen(char *file, int linenum, char **args) {
newsrv->uweight = w - 1;
cur_arg += 2;
}
else if (!strcmp(args[cur_arg], "minconn")) {
newsrv->minconn = atol(args[cur_arg + 1]);
cur_arg += 2;
}
else if (!strcmp(args[cur_arg], "maxconn")) {
newsrv->maxconn = atol(args[cur_arg + 1]);
cur_arg += 2;
@ -8576,7 +8590,7 @@ int cfg_parse_listen(char *file, int linenum, char **args) {
cur_arg += 2;
}
else {
Alert("parsing [%s:%d] : server %s only supports options 'backup', 'cookie', 'check', 'inter', 'rise', 'fall', 'port', 'source', and 'weight'.\n",
Alert("parsing [%s:%d] : server %s only supports options 'backup', 'cookie', 'check', 'inter', 'rise', 'fall', 'port', 'source', 'minconn', 'maxconn' and 'weight'.\n",
file, linenum, newsrv->id);
return -1;
}
@ -9451,6 +9465,12 @@ int readcfgfile(char *file) {
*/
newsrv = curproxy->srv;
while (newsrv != NULL) {
if (newsrv->minconn && !newsrv->maxconn) {
/* only 'minconn' was specified. Let's turn this into maxconn */
newsrv->maxconn = newsrv->minconn;
newsrv->minconn = 0;
}
if (newsrv->maxconn > 0) {
struct task *t;