]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: http: add option prefer-last-server
authorWilly Tarreau <w@1wt.eu>
Sun, 15 Dec 2013 17:58:25 +0000 (18:58 +0100)
committerWilly Tarreau <w@1wt.eu>
Mon, 16 Dec 2013 01:23:54 +0000 (02:23 +0100)
When the load balancing algorithm in use is not deterministic, and a previous
request was sent to a server to which haproxy still holds a connection, it is
sometimes desirable that subsequent requests on a same session go to the same
server as much as possible. Note that this is different from persistence, as
we only indicate a preference which haproxy tries to apply without any form
of warranty. The real use is for keep-alive connections sent to servers. When
this option is used, haproxy will try to reuse the same connection that is
attached to the server instead of rebalancing to another server, causing a
close of the connection. This can make sense for static file servers. It does
not make much sense to use this in combination with hashing algorithms.

doc/configuration.txt
include/types/proxy.h
src/backend.c
src/cfgparse.c

index d0417c047264c31eacda533fa18cc2c14e42e478..b521bf35aabbdd9360daa0804a9eb712f9923c6c 100644 (file)
@@ -3794,7 +3794,9 @@ no option http-keep-alive
 
   If the client request has to go to another backend or another server due to
   content switching or the load balancing algorithm, the idle connection will
-  immediately be closed and a new one re-opened.
+  immediately be closed and a new one re-opened. Option "prefer-last-server" is
+  available to try optimize server selection so that if the server currently
+  attached to an idle connection is usable, it will be used.
 
   In general it is preferred to use "option http-server-close" with application
   servers, and some static servers might benefit from "option http-keep-alive".
@@ -3815,8 +3817,8 @@ no option http-keep-alive
   in a specific instance by prepending the "no" keyword before it.
 
   See also : "option forceclose", "option http-server-close",
-             "option httpclose", "option http-pretend-keepalive" and
-             "1.1. The HTTP transaction model".
+             "option prefer-last-server", "option http-pretend-keepalive",
+             "option httpclose", and "1.1. The HTTP transaction model".
 
 
 option http-no-delay
@@ -4428,6 +4430,30 @@ option pgsql-check [ user <username> ]
   See also: "option httpchk"
 
 
+option prefer-last-server
+no option prefer-last-server
+  Allow multiple load balanced requests to remain on the same server
+  May be used in sections:    defaults | frontend | listen | backend
+                                 yes   |    no    |   yes  |   yes
+  Arguments : none
+
+  When the load balancing algorithm in use is not deterministic, and a previous
+  request was sent to a server to which haproxy still holds a connection, it is
+  sometimes desirable that subsequent requests on a same session go to the same
+  server as much as possible. Note that this is different from persistence, as
+  we only indicate a preference which haproxy tries to apply without any form
+  of warranty. The real use is for keep-alive connections sent to servers. When
+  this option is used, haproxy will try to reuse the same connection that is
+  attached to the server instead of rebalancing to another server, causing a
+  close of the connection. This can make sense for static file servers. It does
+  not make much sense to use this in combination with hashing algorithms.
+
+  If this option has been enabled in a "defaults" section, it can be disabled
+  in a specific instance by prepending the "no" keyword before it.
+
+  See also: "option http-keep-alive"
+
+
 option redispatch
 no option redispatch
   Enable or disable session redistribution in case of connection failure
index de5c337442bfd76b1a4635e66815e062fccd74dc..6c6cc0b9d6dd96f61ed64ff879986983c82e7e62 100644 (file)
@@ -76,7 +76,8 @@ enum pr_mode {
 /* bits for proxy->options */
 #define PR_O_REDISP     0x00000001      /* allow reconnection to dispatch in case of errors */
 #define PR_O_TRANSP     0x00000002      /* transparent mode : use original DEST as dispatch */
-/* unused: 0x04, 0x08, 0x10, 0x20 */
+/* unused: 0x04, 0x08, 0x10 */
+#define PR_O_PREF_LAST  0x00000020      /* prefer last server */
 #define PR_O_DISPATCH   0x00000040      /* use dispatch mode */
 #define PR_O_KEEPALIVE  0x00000080      /* follow keep-alive sessions */
 #define PR_O_FWDFOR     0x00000100      /* conditionally insert x-forwarded-for with client address */
index 7eeed8dc08eefe7f61ed3fdd010b6cfae7edbbe4..c9f0718ec9e0b1dae84e01cfbc999baa6395b8a5 100644 (file)
@@ -532,8 +532,19 @@ int assign_server(struct session *s)
 
        srv = NULL;
        s->target = NULL;
-
-       if (s->be->lbprm.algo & BE_LB_KIND) {
+       conn = objt_conn(s->req->cons->end);
+
+       if (conn && (s->be->options & PR_O_PREF_LAST) &&
+           objt_server(conn->target) && __objt_server(conn->target)->proxy == s->be &&
+           srv_is_usable(__objt_server(conn->target)->state, __objt_server(conn->target)->eweight)) {
+               /* This session was relying on a server in a previous request
+                * and the proxy has "option prefer-current-server" set, so
+                * let's try to reuse the same server.
+                */
+               srv = __objt_server(conn->target);
+               s->target = &srv->obj_type;
+       }
+       else if (s->be->lbprm.algo & BE_LB_KIND) {
                /* we must check if we have at least one server available */
                if (!s->be->lbprm.tot_weight) {
                        err = SRV_STATUS_NOSRV;
index 8d08d01597b526f9b44c7298d442c5702eb46e9e..864a9fb9babf1d9c371e55811c5983e808f3fe89 100644 (file)
@@ -134,6 +134,7 @@ static const struct cfg_opt cfg_opts[] =
        { "httpclose",    PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
        { "http-keep-alive",   PR_O_KEEPALIVE,   PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
        { "http-server-close", PR_O_SERVER_CLO,  PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
+       { "prefer-last-server", PR_O_PREF_LAST,  PR_CAP_BE, 0, PR_MODE_HTTP },
        { "logasap",      PR_O_LOGASAP,    PR_CAP_FE, 0, 0 },
        { "nolinger",     PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
        { "persist",      PR_O_PERSIST,    PR_CAP_BE, 0, 0 },