]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MAJOR: backend: initial work towards connection reuse
authorWilly Tarreau <w@1wt.eu>
Tue, 4 Aug 2015 18:45:52 +0000 (20:45 +0200)
committerWilly Tarreau <w@1wt.eu>
Thu, 6 Aug 2015 09:34:21 +0000 (11:34 +0200)
In connect_server(), if we don't have a connection attached to the
stream-int, we first look into the server's idle_conns list and we
pick the first one there, we detach it from its owner if it had one.
If we used to have a connection, we close it.

This mechanism works well but doesn't scale : as servers increase,
the likeliness that the connection attached to the stream interface
doesn't match the server and gets closed increases.

src/backend.c
src/proto_http.c

index 3c00acfd66fbafdf9515224e6837e1f5341f17c1..b31061a2395f7118a73a46447014f5eee87a40a5 100644 (file)
@@ -1034,6 +1034,33 @@ int connect_server(struct stream *s)
        if (srv_conn)
                reuse = s->target == srv_conn->target;
 
+       if (srv && !reuse) {
+               if (srv_conn) {
+                       srv_conn->owner = NULL;
+                       si_release_endpoint(&s->si[1]);
+                       srv_conn = NULL;
+               }
+
+               if ((s->be->options & PR_O_REUSE_MASK) == PR_O_REUSE_ALWS &&
+                   !LIST_ISEMPTY(&srv->idle_conns)) {
+                       /* We're going to have to pick the first connection
+                        * from this pool and use it for our purposes. We may
+                        * have to get rid of the current idle connection. It
+                        * may move to another pool, but we know we're not
+                        * interested in it.
+                        */
+                       /* pick first connection. We know there's at least one */
+                       srv_conn = LIST_ELEM(srv->idle_conns.n, struct connection *, list);
+
+                       LIST_DEL(&srv_conn->list);
+                       LIST_INIT(&srv_conn->list);
+
+                       si_detach_endpoint(srv_conn->owner);
+                       si_attach_conn(&s->si[1], srv_conn);
+                       reuse = 1;
+               }
+       }
+
        if (reuse) {
                /* Disable connection reuse if a dynamic source is used.
                 * As long as we don't share connections between servers,
index fb831b983326b4c14ec159df141fe948a0fe2187..02ff485d4451a4ca570d15709ec040dad0311a5d 100644 (file)
@@ -5189,7 +5189,13 @@ void http_end_txn_clean_session(struct stream *s)
        /* we're in keep-alive with an idle connection, monitor it */
        if (srv_conn) {
                srv = objt_server(srv_conn->target);
-               si_idle_conn(&s->si[1], srv ? &srv->priv_conns : NULL);
+               if (!srv)
+                       si_idle_conn(&s->si[1], NULL);
+               else if ((srv_conn->flags & CO_FL_PRIVATE) ||
+                        ((s->be->options & PR_O_REUSE_MASK) == PR_O_REUSE_NEVR))
+                       si_idle_conn(&s->si[1], &srv->priv_conns);
+               else
+                       si_idle_conn(&s->si[1], &srv->idle_conns);
        }
 
        s->req.analysers = strm_li(s)->analysers;