Ignore:
Timestamp:
2007-08-31 14:14:06 (7 years ago)
Author:
Cecilie Fritzvold <cecilihf@…>
Branches:
master, 1.2, 3.0, 4.0, experimental-ims
Children:
71f797
Parents:
86a6b9
git-author:
Cecilie Fritzvold <cecilihf@…> (2007-08-31 14:14:06)
git-committer:
Cecilie Fritzvold <cecilihf@…> (2007-08-31 14:14:06)
Message:

Added support for load balancing among backends in varnish. It is still experimental
and very basic, but it should be ready for testing. Two strategies for load balancing
are implemented: a simple round robin, and a simple weighted random. The following
is an example configuration in vcl. The weight parameter for random is optional. Default
is equal weight.

backend foo {

set backend.host = "foo.bar.com";
set backend.port = "http";

}

backend_round_robin rr {

set backend.set = {

{ "foo1.bar.com", "http" }
{ "foo2.bar.com", "http" }
{ "foo3.bar.com", "http" }

};

}

backend_random rrr {

set backend.set = {

{ "foo1.bar.com", "http", 0.3 }
{ "foo2.bar.com", "http", 0.6 }
{ "foo3.bar.com", "http", 0.1 }

};

}

sub vcl_recv {

if {req.http.host ~ "foo"} {

req.backend = foo;

} elseif {req.http.host ~ "bar"} {

req.backend = rr;

} else {

req.backend = rrr;

}

}

git-svn-id:  http://www.varnish-cache.org/svn/trunk/varnish-cache@1931 d4fa192b-c00b-0410-8231-f00ffab90ce4

File:
1 edited

Legend:

Unmodified
Added
Removed
  • lib/libvcl/vcc_backend.c

    r770fb2 r0b0c12  
    6060 
    6161void 
    62 vcc_ParseBackend(struct tokenlist *tl) 
     62vcc_ParseSimpleBackend(struct tokenlist *tl) 
    6363{ 
    6464        struct var *vp; 
     
    8686        ExpectErr(tl, '{'); 
    8787        vcc_NextToken(tl); 
     88         
    8889        while (1) { 
    8990                if (tl->t->tok == '}') 
     
    161162        tl->nbackend++; 
    162163} 
     164 
     165void 
     166vcc_ParseBalancedBackend(struct tokenlist *tl) 
     167{ 
     168        struct var *vp; 
     169        struct token *t_be = NULL; 
     170        struct token *t_host = NULL; 
     171        struct token *t_port = NULL; 
     172        double t_weight = 0; 
     173        const char *ep; 
     174        int cnt = 0; 
     175        int weighted = 0; 
     176        double weight = 0; 
     177        unsigned backend_type = tl->t->tok; 
     178 
     179        vcc_NextToken(tl); 
     180        ExpectErr(tl, ID); 
     181        t_be = tl->t; 
     182        vcc_AddDef(tl, tl->t, R_BACKEND); 
     183        /* 
     184         * The first backend is always referenced because that is the default 
     185         * at the beginning of vcl_recv 
     186         */ 
     187        if (tl->nbackend == 0) 
     188                vcc_AddRef(tl, tl->t, R_BACKEND); 
     189 
     190        /* In the compiled vcl we use these macros to refer to backends */ 
     191        Fh(tl, 1, "#define VGC_backend_%.*s (VCL_conf.backend[%d])\n", 
     192            PF(tl->t), tl->nbackend); 
     193 
     194        vcc_NextToken(tl); 
     195        ExpectErr(tl, '{'); 
     196        vcc_NextToken(tl); 
     197         
     198        while (1) { 
     199                if (tl->t->tok == '}') 
     200                        break; 
     201                ExpectErr(tl, ID); 
     202                if (!vcc_IdIs(tl->t, "set")) { 
     203                        vsb_printf(tl->sb, 
     204                            "Expected 'set', found "); 
     205                        vcc_ErrToken(tl, tl->t); 
     206                        vsb_printf(tl->sb, " at\n"); 
     207                        vcc_ErrWhere(tl, tl->t); 
     208                        return; 
     209                } 
     210                vcc_NextToken(tl); 
     211                ExpectErr(tl, VAR); 
     212                vp = vcc_FindVar(tl, tl->t, vcc_be_vars); 
     213                ERRCHK(tl); 
     214                assert(vp != NULL); 
     215                vcc_NextToken(tl); 
     216                ExpectErr(tl, '='); 
     217                vcc_NextToken(tl); 
     218                if (vp->fmt != SET) { 
     219                        vsb_printf(tl->sb, 
     220                            "Assignments not possible for '%s'\n", vp->name); 
     221                        vcc_ErrWhere(tl, tl->t); 
     222                        return; 
     223                } 
     224                 
     225                ExpectErr(tl, '{'); 
     226                vcc_NextToken(tl); 
     227                 
     228                while (1) { 
     229                        if (tl->t->tok == '}') 
     230                                break; 
     231                                 
     232                        ExpectErr(tl, '{'); 
     233                        vcc_NextToken(tl); 
     234                         
     235                        // Host 
     236                        ExpectErr(tl, CSTR); 
     237                        t_host = tl->t; 
     238                        vcc_NextToken(tl); 
     239                 
     240                        ep = CheckHostPort(t_host->dec, "80"); 
     241                        if (ep != NULL) { 
     242                                vsb_printf(tl->sb, "Backend '%.*s': %s\n", PF(t_be), ep); 
     243                                vcc_ErrWhere(tl, t_host); 
     244                                return; 
     245                        } 
     246                         
     247                        if (tl->t->tok == ',') { 
     248                                vcc_NextToken(tl); 
     249                                 
     250                                // Port 
     251                                 
     252                                ExpectErr(tl, CSTR); 
     253                                t_port = tl->t; 
     254                                vcc_NextToken(tl); 
     255                                 
     256                                ep = CheckHostPort(t_host->dec, t_port->dec); 
     257                                if (ep != NULL) { 
     258                                        vsb_printf(tl->sb, 
     259                                            "Backend '%.*s': %s\n", PF(t_be), ep); 
     260                                        vcc_ErrWhere(tl, t_port); 
     261                                        return; 
     262                                } 
     263                                 
     264                                if (tl->t->tok == ',') { 
     265                                 
     266                                        vcc_NextToken(tl); 
     267                                         
     268                                        // Weight 
     269                                        t_weight = vcc_DoubleVal(tl); 
     270                                        weighted = 1; 
     271                                        weight += t_weight; 
     272                                } 
     273                        } 
     274                                                 
     275                        ExpectErr(tl, '}'); 
     276                        vcc_NextToken(tl); 
     277                 
     278                        Fc(tl, 0, "\nstatic struct vrt_backend_entry bentry_%.*s_%d = {\n", 
     279                                PF(t_be), cnt); 
     280                        Fc(tl, 0, "\t.port = %.*s,\n", PF(t_port)); 
     281                        Fc(tl, 0, "\t.host = %.*s,\n", PF(t_host)); 
     282                        Fc(tl, 0, "\t.weight = %f,\n", t_weight); 
     283                        if (cnt > 0) { 
     284                                Fc(tl, 0, "\t.next = &bentry_%.*s_%d\n", PF(t_be), cnt-1); 
     285                        } /*else { 
     286                                Fc(tl, 0, "\t.next = NULL\n"); 
     287                        }*/ 
     288                        Fc(tl, 0, "};\n"); 
     289                        t_weight = 0; 
     290                        cnt++; 
     291                } 
     292                ExpectErr(tl, '}'); 
     293                vcc_NextToken(tl); 
     294                ExpectErr(tl, ';'); 
     295                vcc_NextToken(tl); 
     296                 
     297                if (t_host == NULL) { 
     298                        vsb_printf(tl->sb, "Backend '%.*s' has no hostname\n", 
     299                        PF(t_be)); 
     300                        vcc_ErrWhere(tl, tl->t); 
     301                        return; 
     302                } 
     303                 
     304                if (weighted && (int)weight != 1) { 
     305                        vsb_printf(tl->sb, "Total weight must be 1\n"); 
     306                        vcc_ErrWhere(tl, tl->t); 
     307                        return; 
     308                } 
     309                 
     310                if (backend_type == T_BACKEND_ROUND_ROBIN) { 
     311                        Fc(tl, 0, "\nstatic struct vrt_round_robin_backend sbe_%.*s = {\n", 
     312                            PF(t_be)); 
     313                        Fc(tl, 0, "\t.name = \"%.*s\",\n", PF(t_be)); 
     314                        Fc(tl, 0, "\t.bentry = &bentry_%.*s_%d\n", PF(t_be), cnt-1); 
     315                        Fc(tl, 0, "};\n"); 
     316                        Fi(tl, 0, "\tVRT_init_round_robin_backend(&VGC_backend_%.*s , &sbe_%.*s);\n", 
     317                            PF(t_be), PF(t_be)); 
     318                } else if (backend_type == T_BACKEND_RANDOM) { 
     319                        Fc(tl, 0, "\nstatic struct vrt_random_backend sbe_%.*s = {\n", 
     320                            PF(t_be)); 
     321                        Fc(tl, 0, "\t.name = \"%.*s\",\n", PF(t_be)); 
     322                        Fc(tl, 0, "\t.weighted = %d,\n", weighted); 
     323                        Fc(tl, 0, "\t.count = %d,\n", cnt); 
     324                        Fc(tl, 0, "\t.bentry = &bentry_%.*s_%d\n", PF(t_be), cnt-1); 
     325                        Fc(tl, 0, "};\n"); 
     326                        Fi(tl, 0, "\tVRT_init_random_backend(&VGC_backend_%.*s , &sbe_%.*s);\n", 
     327                            PF(t_be), PF(t_be)); 
     328                } 
     329                Ff(tl, 0, "\tVRT_fini_backend(VGC_backend_%.*s);\n", PF(t_be)); 
     330 
     331        } 
     332        ExpectErr(tl, '}'); 
     333 
     334        vcc_NextToken(tl); 
     335        tl->nbackend++; 
     336} 
     337 
Note: See TracChangeset for help on using the changeset viewer.