]> err.no Git - varnish/commitdiff
Varnish 2.0 bonus feature #1: backend->max_connections
authorphk <phk@d4fa192b-c00b-0410-8231-f00ffab90ce4>
Tue, 26 Aug 2008 19:59:23 +0000 (19:59 +0000)
committerphk <phk@d4fa192b-c00b-0410-8231-f00ffab90ce4>
Tue, 26 Aug 2008 19:59:23 +0000 (19:59 +0000)
        backend default {
                .host = "127.0.0.1";
                .port = "9080";
                .max_connections = 100;
        }

will limit the simultaneous TCP connections to this backend to 100.

Stats counter backend_busy == "Backend connections too many" tells
how often we have hit this limit for a backend.

git-svn-id: svn+ssh://projects.linpro.no/svn/varnish/trunk@3135 d4fa192b-c00b-0410-8231-f00ffab90ce4

varnish-cache/bin/varnishd/cache.h
varnish-cache/bin/varnishd/cache_backend.c
varnish-cache/bin/varnishd/cache_backend.h
varnish-cache/bin/varnishd/cache_backend_cfg.c
varnish-cache/bin/varnishtest/tests/v00012.vtc [new file with mode: 0644]
varnish-cache/include/stat_field.h
varnish-cache/include/vrt.h
varnish-cache/lib/libvcl/vcc_backend.c
varnish-cache/lib/libvcl/vcc_fixed_token.c

index 460fdf1984c1f6a4b0c0750c40bdddeaa9823b84..50e335b47054a6922bbbb4f2c0e72c503974a663 100644 (file)
@@ -407,7 +407,6 @@ void VBE_Poll(void);
 
 /* cache_backend_cfg.c */
 void VBE_Init(void);
-void VBE_DropRef(struct backend *);
 struct backend *VBE_AddBackend(struct cli *cli, const struct vrt_backend *vb);
 
 /* cache_backend_poll.c */
index 53afab0c03c88410521540a8189aaa4dea3c67d6..831148baa46e67b60f875872df9c01e40157a4ba 100644 (file)
@@ -240,6 +240,7 @@ bes_conn_try(const struct sess *sp, struct backend *bp)
 
        LOCK(&bp->mtx);
        bp->refcount++;
+       bp->n_conn++;           /* It mostly works */
        UNLOCK(&bp->mtx);
 
        s = -1;
@@ -256,6 +257,7 @@ bes_conn_try(const struct sess *sp, struct backend *bp)
 
        if (s < 0) {
                LOCK(&bp->mtx);
+               bp->n_conn--;           
                bp->refcount--;         /* Only keep ref on success */
                UNLOCK(&bp->mtx);
        }
@@ -318,6 +320,11 @@ VBE_GetVbe(struct sess *sp, struct backend *bp)
                return (NULL);
        }
 
+       if (bp->max_conn > 0 && bp->n_conn >= bp->max_conn) {
+               VSL_stats->backend_busy++;
+               return (NULL);
+       }
+
        vc = VBE_NewConn();
        assert(vc->fd == -1);
        AZ(vc->backend);
@@ -347,7 +354,7 @@ VBE_ClosedFd(struct sess *sp)
 
        WSL(sp->wrk, SLT_BackendClose, sp->vbe->fd, "%s", bp->vcl_name);
        TCP_close(&sp->vbe->fd);
-       VBE_DropRef(bp);
+       VBE_DropRefConn(bp);
        sp->vbe->backend = NULL;
        VBE_ReleaseConn(sp->vbe);
        sp->vbe = NULL;
index 6afb9155f931a7268c55ff141b66b1ac9ab28531..bbfc1e4b788893d9e9b6106004e26e7646e73545 100644 (file)
@@ -113,6 +113,8 @@ struct backend {
        struct sockaddr         *ipv6;
        socklen_t               ipv6len;
 
+       unsigned                max_conn;
+       unsigned                n_conn;
        VTAILQ_HEAD(, vbe_conn) connlist;
 
        struct vbp_target       *probe;
@@ -125,6 +127,8 @@ struct vbe_conn *VBE_GetVbe(struct sess *sp, struct backend *bp);
 
 /* cache_backend_cfg.c */
 extern MTX VBE_mtx;
+void VBE_DropRefConn(struct backend *);
+void VBE_DropRef(struct backend *);
 void VBE_DropRefLocked(struct backend *b);
 
 /* cache_backend_poll.c */
index 27aba58121edb811b5a6901a9497fea12ce8790e..af7c4eb95a2d659fe3259540c89669a12655ff2b 100644 (file)
@@ -132,6 +132,18 @@ VBE_DropRef(struct backend *b)
        VBE_DropRefLocked(b);
 }
 
+void
+VBE_DropRefConn(struct backend *b)
+{
+
+       CHECK_OBJ_NOTNULL(b, BACKEND_MAGIC);
+
+       LOCK(&b->mtx);
+       assert(b->n_conn > 0);
+       b->n_conn--;
+       VBE_DropRefLocked(b);
+}
+
 /*--------------------------------------------------------------------*/
 
 static void
@@ -210,6 +222,7 @@ VBE_AddBackend(struct cli *cli, const struct vrt_backend *vb)
        REPLACE(b->hosthdr, vb->hosthdr);
 
        b->connect_timeout = vb->connect_timeout;
+       b->max_conn = vb->max_connections;
 
        /*
         * Copy over the sockaddrs
@@ -252,10 +265,9 @@ cli_debug_backend(struct cli *cli, const char * const *av, void *priv)
        ASSERT_CLI();
        VTAILQ_FOREACH(b, &backends, list) {
                CHECK_OBJ_NOTNULL(b, BACKEND_MAGIC);
-               cli_out(cli, "%p %s %d\n",
-                   b,
-                   b->vcl_name,
-                   b->refcount);
+               cli_out(cli, "%p %s %d %d/%d\n",
+                   b, b->vcl_name, b->refcount,
+                   b->n_conn, b->max_conn);
        }
 }
 
diff --git a/varnish-cache/bin/varnishtest/tests/v00012.vtc b/varnish-cache/bin/varnishtest/tests/v00012.vtc
new file mode 100644 (file)
index 0000000..fa4ba54
--- /dev/null
@@ -0,0 +1,43 @@
+# $Id$
+
+test "Check backend connection limit"
+
+server s1 {
+       rxreq
+       sema r1 sync 2
+       sema r2 sync 2
+       txresp
+} -start
+
+varnish v1 -vcl {
+
+       backend default {
+               .host = "127.0.0.1";
+               .port = "9080";
+               .max_connections = 1;
+       }
+       sub vcl_recv {
+               pass;
+       }
+} -start
+
+client c1 {
+       txreq
+       rxresp
+       expect resp.status == 200
+} -start
+
+
+client c2 {
+       sema r1 sync 2
+       txreq
+       rxresp
+       expect resp.status == 503
+} -run
+
+varnish v1 -cli "debug.backend"
+
+sema r2 sync 2
+client c1 -wait
+
+varnish v1 -expect backend_busy == 1
index 86f7b6786dd42649fcdfc02b4f0d1d3bb706dcc4..beec28ff8cd6737b5b317000983c509633ce0929 100644 (file)
@@ -38,6 +38,7 @@ MAC_STAT(cache_miss,          uint64_t, 'a', "Cache misses")
 
 MAC_STAT(backend_conn,         uint64_t, 'a', "Backend connections success")
 MAC_STAT(backend_unhealthy,    uint64_t, 'a', "Backend connections not attempted")
+MAC_STAT(backend_busy,         uint64_t, 'a', "Backend connections too many")
 MAC_STAT(backend_fail,         uint64_t, 'a', "Backend connections failures")
 MAC_STAT(backend_reuse,                uint64_t, 'a', "Backend connections reuses")
 MAC_STAT(backend_recycle,      uint64_t, 'a', "Backend connections recycles")
index 35bc1d7fcbdefbf6a8d88af60d5c5a3761f81903..243c5d659d22601e24936dd0fadaf3a3bb3b07e8 100644 (file)
@@ -69,6 +69,7 @@ struct vrt_backend {
        const unsigned char             *ipv6_sockaddr;
 
        double                          connect_timeout;
+       unsigned                        max_connections;
        struct vrt_backend_probe        probe;
 };
 
index 7d93e3f499d541abec31087876223d0276b9b847..284a6e2a8f1e68f907339d0be7ab14f47560102f 100644 (file)
@@ -476,13 +476,16 @@ vcc_ParseHostDef(struct tokenlist *tl, int *nbh, const struct token *name, const
        const char *ep;
        struct fld_spec *fs;
        struct vsb *vsb;
+       unsigned u;
 
        fs = vcc_FldSpec(tl,
            "!host",
            "?port",
            "?host_header",
            "?connect_timeout",
-           "?probe", NULL);
+           "?probe",
+           "?max_connections",
+           NULL);
        t_first = tl->t;
 
        ExpectErr(tl, '{');
@@ -546,6 +549,13 @@ vcc_ParseHostDef(struct tokenlist *tl, int *nbh, const struct token *name, const
                        Fb(tl, 0, ",\n");
                        ExpectErr(tl, ';');
                        vcc_NextToken(tl);
+               } else if (vcc_IdIs(t_field, "max_connections")) {
+                       u = vcc_UintVal(tl);
+                       vcc_NextToken(tl);
+                       ERRCHK(tl);
+                       ExpectErr(tl, ';');
+                       vcc_NextToken(tl);
+                       Fb(tl, 0, "\t.max_connections = %u,\n", u);
                } else if (vcc_IdIs(t_field, "probe")) {
                        vcc_ParseProbe(tl);
                        ERRCHK(tl);
index ff59e2282f0754fe61d3ed7c983af1d5427da21e..3ee45b2575b63224079773465807f478a6d2497f 100644 (file)
@@ -349,6 +349,7 @@ vcl_output_lang_h(struct vsb *sb)
        vsb_cat(sb, "   const unsigned char             *ipv6_sockaddr;\n");
        vsb_cat(sb, "\n");
        vsb_cat(sb, "   double                          connect_timeout;\n");
+       vsb_cat(sb, "   unsigned                        max_connections;\n");
        vsb_cat(sb, "   struct vrt_backend_probe        probe;\n");
        vsb_cat(sb, "};\n");
        vsb_cat(sb, "\n");