]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
[MEDIUM] add support for "maxqueue" to limit server queue overload
authorElijah Epifanov <epifanov@hh.ru>
Thu, 25 Oct 2007 18:15:38 +0000 (20:15 +0200)
committerWilly Tarreau <w@1wt.eu>
Thu, 25 Oct 2007 18:15:38 +0000 (20:15 +0200)
This patch adds the "maxqueue" parameter to the server. This allows new
sessions to be immediately rebalanced when the server's queue is filled.
It's useful when session stickiness is just a performance boost (even a
huge one) but not a requirement.

This should only be used if session affinity isn't a hard functional
requirement but provides performance boost by keeping server-local
caches hot and compact).

Absence of 'maxqueue' option means unlimited queue. When queue gets filled
up to 'maxqueue' client session is moved from server-local queue to a global
one.

doc/haproxy-en.txt
doc/haproxy-fr.txt
include/types/server.h
src/backend.c
src/cfgparse.c
src/dumpstats.c

index 09d311e52e6ca3669f9eb861e6f2d68398aae97a..3e8ce107b59319b18a43d7fb51788bd42ec48db0 100644 (file)
@@ -1364,6 +1364,21 @@ 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.
 
+It is possible to limit server queue length in order to rebalance excess
+sessions between less busy application servers IF session affinity isn't
+hard functional requirement (for example it just gives huge performance boost
+by keeping server-local caches hot and compact). 'maxqueue' option sets a
+queue limit on a server, as in example below:
+
+... (just the same as in example above)
+        server pentium3-800 192.168.1.1:80 cookie s1 weight  8 minconn 10 maxconn 100 check maxqueue 50
+        server opteron-2.0G 192.168.1.2:80 cookie s2 weight 20 minconn 30 maxconn 300 check maxqueue 200
+        server opteron-2.4G 192.168.1.3:80 cookie s3 weight 24 minconn 30 maxconn 300 check
+
+Absence of 'maxqueue' option means unlimited queue. When queue gets filled
+up to 'maxqueue' client session is moved from server-local queue to a global
+one.
+
 Notes :
 -------
   - The requests will not stay indefinitely in the queue, they follow the
index d29259fc7c71dc18070e6fc2ad676366a7a7ada5..7974546bf4cd23f2f0b52739be7ad896ec850ca3 100644 (file)
@@ -1391,6 +1391,23 @@ connexions simultan
 recevra seulement 10 connexions simultanées tant que le proxy sera sous les 1000
 sessions.
 
+Il est possible de limiter la taille de la file d'attente dans le but de
+redistribuer les connexions destinées à un serveur en particulier qui sont trop
+loin pour avoir une chance d'être servies en un temps raisonnable. Ceci n'est
+acceptable que dans le cas où l'affinité entre le client et le serveur n'est
+pas obligatoire, mais motivée uniquement par des raisons de performances, par
+exemple, par l'utilisation d'un cache local au serveur. L'option 'maxqueue'
+permet de préciser la limite par serveur, tel que dans l'exemple ci-dessous :
+
+... (même exemple que précédemment)
+        server pentium3-800 192.168.1.1:80 cookie s1 weight  8 minconn 10 maxconn 100 check maxqueue 50
+        server opteron-2.0G 192.168.1.2:80 cookie s2 weight 20 minconn 30 maxconn 300 check maxqueue 200
+        server opteron-2.4G 192.168.1.3:80 cookie s3 weight 24 minconn 30 maxconn 300 check
+
+En l'absence du paramètre 'maxqueue', la file d'un serveur n'a pas de limite
+définie. Dans le cas contraire, lorsque la file atteint la limite fixée par
+'maxqueue', les clients sont déplacés vers la file globale.
+
 Notes :
 -------
   - la requête ne restera pas indéfiniment en file d'attente, elle est
index 62179f33d89de96b91ca93df8ffe61f18d564808..6e3a9138b450569e5f1a551bd52faddd4a253cf8 100644 (file)
@@ -64,6 +64,7 @@ struct server {
        int cur_sess, cur_sess_max;             /* number of currently active sessions (including syn_sent) */
        unsigned maxconn, minconn;              /* max # of active sessions (0 = unlimited), min# for dynamic limit. */
        int nbpend, nbpend_max;                 /* number of pending connections */
+       int maxqueue;                           /* maximum number of pending connections allowed */
        struct list pendconns;                  /* pending connections */
        struct task *queue_mgt;                 /* the task associated to the queue processing */
 
index 596d5676cafffdf428815d9e57fcf957b753308e..faf5db89a9cee80ab033dc50d8ae64a33c3b050e 100644 (file)
@@ -294,19 +294,25 @@ int assign_server_and_queue(struct session *s)
                return SRV_STATUS_INTERNAL;
 
        if (s->flags & SN_ASSIGNED) {
-               /* a server does not need to be assigned, perhaps because we're in
-                * direct mode, or in dispatch or transparent modes where the server
-                * is not needed.
-                */
-               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;
-                       else
-                               return SRV_STATUS_FULL;
+               if (s->srv && s->srv->maxqueue > 0 && s->srv->nbpend >= s->srv->maxqueue) {
+                       s->flags &= ~(SN_DIRECT | SN_ASSIGNED | SN_ADDR_SET);
+                       s->srv = NULL;
+                       http_flush_cookie_flags(&s->txn);
+               } else {
+                       /* a server does not need to be assigned, perhaps because we're in
+                        * direct mode, or in dispatch or transparent modes where the server
+                        * is not needed.
+                        */
+                       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;
+                               else
+                                       return SRV_STATUS_FULL;
+                       }
+                       return SRV_STATUS_OK;
                }
-               return SRV_STATUS_OK;
        }
 
        /* a server needs to be assigned */
index 7b73e0bee1959ee8ab1ea0a6f8fe8f29987f521b..89c8c1997ff881efce6db40637b3131a163ca06c 100644 (file)
@@ -1413,6 +1413,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args)
                newsrv->fall = DEF_FALLTIME;
                newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
                newsrv->uweight = 1;
+               newsrv->maxqueue = 0;
 
                cur_arg = 3;
                while (*args[cur_arg]) {
@@ -1465,6 +1466,10 @@ int cfg_parse_listen(const char *file, int linenum, char **args)
                                newsrv->maxconn = atol(args[cur_arg + 1]);
                                cur_arg += 2;
                        }
+                       else if (!strcmp(args[cur_arg], "maxqueue")) {
+                               newsrv->maxqueue = atol(args[cur_arg + 1]);
+                               cur_arg += 2;
+                       }
                        else if (!strcmp(args[cur_arg], "check")) {
                                global.maxsock++;
                                do_check = 1;
@@ -1521,7 +1526,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args)
                        }
 #endif
                        else {
-                               Alert("parsing [%s:%d] : server %s only supports options 'backup', 'cookie', 'check', 'inter', 'rise', 'fall', 'addr', 'port', 'source', 'minconn', 'maxconn' and 'weight'.\n",
+                               Alert("parsing [%s:%d] : server %s only supports options 'backup', 'cookie', 'check', 'inter', 'rise', 'fall', 'addr', 'port', 'source', 'minconn', 'maxconn', 'maxqueue', and 'weight'.\n",
                                      file, linenum, newsrv->id);
                                return -1;
                        }
index 7ec4b565be0a2cf8f08f4bd8c74275f767498d14..4d34c474a11f58d80580ad9fa5b86d25438c3ef1 100644 (file)
@@ -372,7 +372,7 @@ int stats_dump_http(struct session *s, struct uri_auth *uri, int flags)
                             "ereq,econ,eresp,"
                             "wretr,wredis,"
                             "status,weight,act,bck,"
-                            "chkfail,chkdown,lastchg,downtime,"
+                            "chkfail,chkdown,lastchg,downtime,qlimit,"
                             "\n");
                }
                if (buffer_write_chunk(rep, &msg) != 0)
@@ -582,20 +582,20 @@ int stats_dump_proxy(struct session *s, struct proxy *px, struct uri_auth *uri,
                if (flags & STAT_FMT_HTML) {
                        /* print a new table */
                        chunk_printf(&msg, sizeof(trash),
-                                    "<table cols=\"23\" class=\"tbl\" width=\"100%%\">\n"
+                                    "<table cols=\"24\" class=\"tbl\" width=\"100%%\">\n"
                                     "<tr align=\"center\" class=\"titre\">"
                                     "<th colspan=2 class=\"pxname\">%s</th>"
                                     "<th colspan=21 class=\"empty\"></th>"
                                     "</tr>\n"
                                     "<tr align=\"center\" class=\"titre\">"
                                     "<th rowspan=2></th>"
-                                    "<th colspan=2>Queue</th><th colspan=4>Sessions</th>"
+                                    "<th colspan=3>Queue</th><th colspan=4>Sessions</th>"
                                     "<th colspan=2>Bytes</th><th colspan=2>Denied</th>"
                                     "<th colspan=3>Errors</th><th colspan=2>Warnings</th>"
                                     "<th colspan=7>Server</th>"
                                     "</tr>\n"
                                     "<tr align=\"center\" class=\"titre\">"
-                                    "<th>Cur</th><th>Max</th><th>Cur</th><th>Max</th>"
+                                    "<th>Cur</th><th>Max</th><th>Limit</th><th>Cur</th><th>Max</th>"
                                     "<th>Limit</th><th>Cumul</th><th>In</th><th>Out</th>"
                                     "<th>Req</th><th>Resp</th><th>Req</th><th>Conn</th>"
                                     "<th>Resp</th><th>Retr</th><th>Redis</th>"
@@ -617,7 +617,7 @@ int stats_dump_proxy(struct session *s, struct proxy *px, struct uri_auth *uri,
                        if (flags & STAT_FMT_HTML) {
                                chunk_printf(&msg, sizeof(trash),
                                     /* name, queue */
-                                    "<tr align=center class=\"frontend\"><td>Frontend</td><td colspan=2></td>"
+                                    "<tr align=center class=\"frontend\"><td>Frontend</td><td colspan=3></td>"
                                     /* sessions : current, max, limit, cumul */
                                     "<td align=right>%d</td><td align=right>%d</td>"
                                     "<td align=right>%d</td><td align=right>%d</td>"
@@ -657,7 +657,7 @@ int stats_dump_proxy(struct session *s, struct proxy *px, struct uri_auth *uri,
                                     /* server status : reflect frontend status */
                                     "%s,"
                                     /* rest of server: nothing */
-                                    ",,,,,,,"
+                                    ",,,,,,,,"
                                     "\n",
                                     px->id,
                                     px->feconn, px->feconn_max, px->maxconn, px->cum_feconn,
@@ -709,8 +709,8 @@ int stats_dump_proxy(struct session *s, struct proxy *px, struct uri_auth *uri,
                                chunk_printf(&msg, sizeof(trash),
                                     /* name */
                                     "<tr align=\"center\" class=\"%s%d\"><td>%s</td>"
-                                    /* queue : current, max */
-                                    "<td align=right>%d</td><td align=right>%d</td>"
+                                    /* queue : current, max, limit */
+                                    "<td align=right>%d</td><td align=right>%d</td><td align=right>%s</td>"
                                     /* sessions : current, max, limit, cumul */
                                     "<td align=right>%d</td><td align=right>%d</td>"
                                     "<td align=right>%s</td><td align=right>%d</td>"
@@ -725,8 +725,8 @@ int stats_dump_proxy(struct session *s, struct proxy *px, struct uri_auth *uri,
                                     "",
                                     (sv->state & SRV_BACKUP) ? "backup" : "active",
                                     sv_state, sv->id,
-                                    sv->nbpend, sv->nbpend_max,
-                                    sv->cur_sess, sv->cur_sess_max, sv->maxconn ? ultoa(sv->maxconn) : "-", sv->cum_sess,
+                                    sv->nbpend, sv->nbpend_max, LIM2A0(sv->maxqueue, "-"),
+                                    sv->cur_sess, sv->cur_sess_max, LIM2A1(sv->maxconn, "-"), sv->cum_sess,
                                     sv->bytes_in, sv->bytes_out,
                                     sv->failed_secu,
                                     sv->failed_conns, sv->failed_resp,
@@ -809,12 +809,17 @@ int stats_dump_proxy(struct session *s, struct proxy *px, struct uri_auth *uri,
                                /* check failures: unique, fatal; last change, total downtime */
                                if (sv->state & SRV_CHECKED)
                                        chunk_printf(&msg, sizeof(trash),
-                                            "%d,%d,%d,%d,\n",
+                                            "%d,%d,%d,%d,",
                                             sv->failed_checks, sv->down_trans,
                                             now.tv_sec - sv->last_change, srv_downtime(sv));
                                else
                                        chunk_printf(&msg, sizeof(trash),
-                                            ",,,,\n");
+                                            ",,,,");
+
+                               /* queue limit and EOL */
+                               chunk_printf(&msg, sizeof(trash),
+                                    "%s,\n",
+                                    LIM2A0(sv->maxqueue, ""));
                        }
                        if (buffer_write_chunk(rep, &msg) != 0)
                                return 0;
@@ -845,7 +850,7 @@ int stats_dump_proxy(struct session *s, struct proxy *px, struct uri_auth *uri,
                                     /* name */
                                     "<tr align=center class=\"backend\"><td>Backend</td>"
                                     /* queue : current, max */
-                                    "<td align=right>%d</td><td align=right>%d</td>"
+                                    "<td align=right>%d</td><td align=right>%d</td><td></td>"
                                     /* sessions : current, max, limit, cumul. */
                                     "<td align=right>%d</td><td align=right>%d</td><td align=right>%d</td><td align=right>%d</td>"
                                     /* bytes : in, out */
@@ -903,7 +908,7 @@ int stats_dump_proxy(struct session *s, struct proxy *px, struct uri_auth *uri,
                                     "%d,%d,%d,"
                                     /* rest of backend: nothing, down transformations,
                                      * last change, total downtime. */
-                                    ",%d,%d,%d,"
+                                    ",%d,%d,%d,,"
                                     "\n",
                                     px->id,
                                     px->nbpend /* or px->totpend ? */, px->nbpend_max,