]> err.no Git - varnish/commitdiff
Added a round robin director. The round robin director can be created like this:
authorpetter <petter@d4fa192b-c00b-0410-8231-f00ffab90ce4>
Mon, 14 Jul 2008 12:59:10 +0000 (12:59 +0000)
committerpetter <petter@d4fa192b-c00b-0410-8231-f00ffab90ce4>
Mon, 14 Jul 2008 12:59:10 +0000 (12:59 +0000)
director batman round-robin {
{ .backend = b1; }
{ .backend = b2; }
{ .backend = b3; }
}

sub vcl_recv {
set req.backend = batman;
}

The backend will then be chosen in a round robin fashion.

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

varnish-cache/bin/varnishd/Makefile.am
varnish-cache/bin/varnishd/cache_dir_round_robin.c [new file with mode: 0644]
varnish-cache/bin/varnishtest/tests/v00009.vtc [new file with mode: 0644]
varnish-cache/include/vrt.h
varnish-cache/lib/libvcl/Makefile.am
varnish-cache/lib/libvcl/vcc_backend.c
varnish-cache/lib/libvcl/vcc_compile.h
varnish-cache/lib/libvcl/vcc_dir_round_robin.c [new file with mode: 0644]
varnish-cache/lib/libvcl/vcc_fixed_token.c

index 770cf98e4da9c84da6d2cae688cc67160b5c8f54..93524f4f91bcf59fdb954b6eb7f090b7821dcc54 100644 (file)
@@ -18,6 +18,7 @@ varnishd_SOURCES = \
        cache_center.c \
        cache_cli.c \
        cache_dir_random.c \
+       cache_dir_round_robin.c \
        cache_dir_simple.c \
        cache_expire.c \
        cache_fetch.c \
diff --git a/varnish-cache/bin/varnishd/cache_dir_round_robin.c b/varnish-cache/bin/varnishd/cache_dir_round_robin.c
new file mode 100644 (file)
index 0000000..0a44f8d
--- /dev/null
@@ -0,0 +1,127 @@
+/*-
+ * Copyright (c) 2006 Verdens Gang AS
+ * Copyright (c) 2006-2008 Linpro AS
+ * All rights reserved.
+ *
+ * Author: Petter Knudsen <petter@linpro.no>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: cache_dir_round_robin.c 2906 2008-07-08 10:29:07Z phk $
+ *
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "shmlog.h"
+#include "cache.h"
+#include "vrt.h"
+
+/*--------------------------------------------------------------------*/
+
+struct vdi_round_robin_host {
+       struct backend          *backend;
+};
+
+struct vdi_round_robin {
+       unsigned                magic;
+#define VDI_ROUND_ROBIN_MAGIC  0x2114a178
+       struct director         dir;
+       struct backend          *backend;
+       struct vdi_round_robin_host     *hosts;
+       unsigned                nhosts;
+       unsigned                next_host;
+};
+
+
+static struct backend *
+vdi_round_robin_choose(struct sess *sp)
+{
+       struct vdi_round_robin *vs;
+       struct backend *backend;
+
+       CHECK_OBJ_NOTNULL(sp->director, DIRECTOR_MAGIC);
+       CAST_OBJ_NOTNULL(vs, sp->director->priv, VDI_ROUND_ROBIN_MAGIC);
+
+       backend = vs->hosts[ vs->next_host ].backend;
+       vs->next_host = (vs->next_host + 1) % vs->nhosts;
+
+       return (backend);
+}
+
+static void
+vdi_round_robin_fini(struct director *d)
+{
+       int i;
+       struct vdi_round_robin *vs;
+       struct vdi_round_robin_host *vh;
+
+       CHECK_OBJ_NOTNULL(d, DIRECTOR_MAGIC);
+       CAST_OBJ_NOTNULL(vs, d->priv, VDI_ROUND_ROBIN_MAGIC);
+       
+       vh = vs->hosts;
+       for (i = 0; i < vs->nhosts; i++, vh++)
+               VBE_DropRef(vh->backend);
+       free(vs->hosts);
+       vs->dir.magic = 0;
+       vs->next_host = 0;
+       FREE_OBJ(vs);
+}
+
+void
+VRT_init_dir_round_robin(struct cli *cli, struct director **bp, const struct vrt_dir_round_robin *t)
+{
+       struct vdi_round_robin *vs;
+       const struct vrt_dir_round_robin_entry *te;
+       struct vdi_round_robin_host *vh;
+       int i;
+       
+       (void)cli;
+
+       ALLOC_OBJ(vs, VDI_ROUND_ROBIN_MAGIC);
+       XXXAN(vs);
+       vs->hosts = calloc(sizeof *vh, t->nmember);
+       XXXAN(vs->hosts);
+
+       vs->dir.magic = DIRECTOR_MAGIC;
+       vs->dir.priv = vs;
+       vs->dir.name = "round_robin";
+       vs->dir.choose = vdi_round_robin_choose;
+       vs->dir.fini = vdi_round_robin_fini;
+
+       vh = vs->hosts;
+       te = t->members;
+       for (i = 0; i < t->nmember; i++, vh++, te++)
+               vh->backend = VBE_AddBackend(cli, te->host);
+       vs->nhosts = t->nmember;
+       vs->next_host = 0;
+
+       *bp = &vs->dir;
+}
diff --git a/varnish-cache/bin/varnishtest/tests/v00009.vtc b/varnish-cache/bin/varnishtest/tests/v00009.vtc
new file mode 100644 (file)
index 0000000..515ca12
--- /dev/null
@@ -0,0 +1,67 @@
+# $Id$
+
+test "Test round robin director"
+
+server s1 -listen 127.0.0.1:2000 {
+       rxreq
+       txresp -body "1"
+} -start
+
+server s2 -listen 127.0.0.1:3000 {
+       rxreq
+       txresp -body "22"
+} -start
+
+
+server s3 -listen 127.0.0.1:4000 {
+       rxreq
+       txresp -body "333"
+} -start
+
+server s4 -listen 127.0.0.1:5000 {
+       rxreq
+       txresp -body "4444"
+} -start
+
+
+varnish v1 -vcl+backend {
+       director batman round-robin {
+               { .backend = s1; }
+               { .backend = s2; }
+               { .backend = s3; }
+               { .backend = s4; }
+       }
+
+       sub vcl_recv {
+               set req.backend = batman;
+       }
+} -start
+
+client c1 {
+       timeout 3
+       txreq -url "/foo1"
+       rxresp
+       expect resp.http.content-length == 1
+       txreq -url "/foo2"
+       rxresp
+       expect resp.http.content-length == 2
+       txreq -url "/foo3"
+       rxresp
+       expect resp.http.content-length == 3
+       txreq -url "/foo4"
+       rxresp
+       expect resp.http.content-length == 4
+} -run
+
+server s1 -start
+server s2 -start
+
+client c2 {
+       timeout 3
+       txreq -url "/foo11"
+       rxresp
+       expect resp.http.content-length == 1
+       txreq -url "/foo22"
+       rxresp
+       expect resp.http.content-length == 2
+} -run
index 7ef1a4b7b1dd96bebb731a1c62c4d0a99f94145b..013c0778437f25965b582e03a7cf006e2921e814 100644 (file)
@@ -91,6 +91,21 @@ struct vrt_dir_random {
        const struct vrt_dir_random_entry       *members;
 };
 
+/*
+ * A director with round robin selection
+ */
+
+struct vrt_dir_round_robin_entry {
+       const struct vrt_backend                *host;
+};
+
+struct vrt_dir_round_robin {
+       const char                              *name;
+       unsigned                                nmember;
+       const struct vrt_dir_round_robin_entry  *members;
+};
+
+
 /*
  * other stuff.
  * XXX: document when bored
@@ -147,6 +162,7 @@ void VRT_Rollback(struct sess *sp);
 /* Backend related */
 void VRT_init_dir_simple(struct cli *, struct director **, const struct vrt_dir_simple *);
 void VRT_init_dir_random(struct cli *, struct director **, const struct vrt_dir_random *);
+void VRT_init_dir_round_robin(struct cli *, struct director **, const struct vrt_dir_round_robin *);
 void VRT_fini_dir(struct cli *, struct director *);
 
 char *VRT_IP_string(const struct sess *sp, const struct sockaddr *sa);
index 388ac77ebd217a2a43cfaa092fc76b23b84e06eb..8910e8b1dbef064e60139316a4aa7010b4f77ae1 100644 (file)
@@ -14,6 +14,7 @@ libvcl_la_SOURCES = \
        vcc_backend.c \
        vcc_compile.c \
        vcc_dir_random.c \
+       vcc_dir_round_robin.c \
        vcc_parse.c \
        vcc_fixed_token.c \
        vcc_obj.c \
index 0f43b548ec7ebfa764f37c06c6d2f3cafff03039..ad7eb262ee1537086af5d39c098d2a795d90cfa1 100644 (file)
@@ -656,6 +656,7 @@ static const struct dirlist {
        parsedirector_f *func;
 } dirlist[] = {
        { "random",     vcc_ParseRandomDirector },
+       { "round-robin",        vcc_ParseRoundRobinDirector },
        { NULL,         NULL }
 };
 
index 911e511fbbdb3a1e73145fb218072cc674ccada8..05a83c47fa9c02d29dc1b16d9aab9b7bce183da3 100644 (file)
@@ -178,6 +178,9 @@ void *TlAlloc(struct tokenlist *tl, unsigned len);
 /* vcc_dir_random.c */
 parsedirector_f vcc_ParseRandomDirector;
 
+/* vcc_dir_round_robin.c */
+parsedirector_f vcc_ParseRoundRobinDirector;
+
 /* vcc_obj.c */
 extern struct var vcc_vars[];
 
diff --git a/varnish-cache/lib/libvcl/vcc_dir_round_robin.c b/varnish-cache/lib/libvcl/vcc_dir_round_robin.c
new file mode 100644 (file)
index 0000000..eda2acb
--- /dev/null
@@ -0,0 +1,108 @@
+/*-
+ * Copyright (c) 2006 Verdens Gang AS
+ * Copyright (c) 2006-2008 Linpro AS
+ * All rights reserved.
+ *
+ * Author: Petter Knudsen <petter@linpro.no>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: vcc_dir_random.c 2900 2008-07-08 07:30:42Z phk $
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netdb.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include "vsb.h"
+
+#include "vcc_priv.h"
+#include "vcc_compile.h"
+#include "libvarnish.h"
+
+/*--------------------------------------------------------------------
+ * Parse directors
+ */
+
+void
+vcc_ParseRoundRobinDirector(struct tokenlist *tl, const struct token *t_policy, const struct token *t_dir)
+{
+       struct token *t_field, *t_be;
+       int nbh, nelem;
+       struct fld_spec *fs;
+
+       fs = vcc_FldSpec(tl, "!backend", NULL);
+
+       Fc(tl, 0,
+           "\nstatic const struct vrt_dir_round_robin_entry vdrre_%.*s[] = {\n",
+           PF(t_dir));
+
+       for (nelem = 0; tl->t->tok != '}'; nelem++) {   /* List of members */
+               t_be = tl->t;
+               vcc_ResetFldSpec(fs);
+               nbh = -1;
+
+               ExpectErr(tl, '{');
+               vcc_NextToken(tl);
+               Fc(tl, 0, "\t{");
+       
+               while (tl->t->tok != '}') {     /* Member fields */
+                       vcc_IsField(tl, &t_field, fs);
+                       ERRCHK(tl);
+                       if (vcc_IdIs(t_field, "backend")) {
+                               vcc_ParseBackendHost(tl, &nbh,
+                                   t_dir, t_policy, nelem);
+                               Fc(tl, 0, " .host = &bh_%d,", nbh);
+                               ERRCHK(tl);
+                       } else {
+                               ErrInternal(tl);
+                       }
+               }
+               vcc_FieldsOk(tl, fs);
+               if (tl->err) {
+                       vsb_printf(tl->sb,
+                           "\nIn member host specfication starting at:\n");
+                       vcc_ErrWhere(tl, t_be);
+                       return;
+               }
+               Fc(tl, 0, " },\n");
+               vcc_NextToken(tl);
+       }
+       Fc(tl, 0, "};\n");
+       Fc(tl, 0,
+           "\nstatic const struct vrt_dir_round_robin vdrr_%.*s = {\n",
+           PF(t_dir));
+       Fc(tl, 0, "\t.name = \"%.*s\",\n", PF(t_dir));
+       Fc(tl, 0, "\t.nmember = %d,\n", nelem);
+       Fc(tl, 0, "\t.members = vdrre_%.*s,\n", PF(t_dir));
+       Fc(tl, 0, "};\n");
+       Fi(tl, 0,
+           "\tVRT_init_dir_round_robin(cli, &VGC_backend_%.*s , &vdrr_%.*s);\n",
+           PF(t_dir), PF(t_dir));
+       Ff(tl, 0, "\tVRT_fini_dir(cli, VGC_backend_%.*s);\n", PF(t_dir));
+}
index b0d87486daca226777e5d2ace6e490ebaba37c14..727467956f2e587d68d59cc697ea0858f6ec4ab2 100644 (file)
@@ -430,6 +430,21 @@ vcl_output_lang_h(struct vsb *sb)
        vsb_cat(sb, "};\n");
        vsb_cat(sb, "\n");
        vsb_cat(sb, "/*\n");
+       vsb_cat(sb, " * A director with round robin selection\n");
+       vsb_cat(sb, " */\n");
+       vsb_cat(sb, "\n");
+       vsb_cat(sb, "struct vrt_dir_round_robin_entry {\n");
+       vsb_cat(sb, "   const struct vrt_backend                *host;\n");
+       vsb_cat(sb, "};\n");
+       vsb_cat(sb, "\n");
+       vsb_cat(sb, "struct vrt_dir_round_robin {\n");
+       vsb_cat(sb, "   const char                              *name;\n");
+       vsb_cat(sb, "   unsigned                                nmember;\n");
+       vsb_cat(sb, "   const struct vrt_dir_round_robin_entry  *members;\n");
+       vsb_cat(sb, "};\n");
+       vsb_cat(sb, "\n");
+       vsb_cat(sb, "\n");
+       vsb_cat(sb, "/*\n");
        vsb_cat(sb, " * other stuff.\n");
        vsb_cat(sb, " * XXX: document when bored\n");
        vsb_cat(sb, " */\n");
@@ -485,6 +500,7 @@ vcl_output_lang_h(struct vsb *sb)
        vsb_cat(sb, "/* Backend related */\n");
        vsb_cat(sb, "void VRT_init_dir_simple(struct cli *, struct director **, const struct vrt_dir_simple *);\n");
        vsb_cat(sb, "void VRT_init_dir_random(struct cli *, struct director **, const struct vrt_dir_random *);\n");
+       vsb_cat(sb, "void VRT_init_dir_round_robin(struct cli *, struct director **, const struct vrt_dir_round_robin *);\n");
        vsb_cat(sb, "void VRT_fini_dir(struct cli *, struct director *);\n");
        vsb_cat(sb, "\n");
        vsb_cat(sb, "char *VRT_IP_string(const struct sess *sp, const struct sockaddr *sa);\n");