Commit 90b058b8 authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

Add a random director to VMOD.directors

parent f8b37ce3
......@@ -21,21 +21,23 @@ client c1 {
} -run
varnish v1 -vcl {
director bar random {
{
.backend = {
.host = "${bad_ip}"; .port = "9080";
}
.weight = 1;
}
import directors from "${topbuild}/lib/libvmod_directors/.libs/libvmod_directors.so" ;
backend b1 {
.host = "${bad_ip}"; .port = "9080";
}
sub vcl_init {
new bar = directors.random();
bar.add_backend(b1, 1);
}
sub vcl_recv {
error 200 "ok";
set req.backend = bar.backend();
error 200 "ok";
}
sub vcl_error {
set obj.http.X-Backend-Name = req.backend;
set obj.http.X-Backend-Name = req.backend;
}
}
......
varnishtest "Test refcounting backends from director"
# XXX: This test is probably not relevant with VMOD.directors
varnish v1 -vcl {
import directors from "${topbuild}/lib/libvmod_directors/.libs/libvmod_directors.so" ;
backend node1 { .host = "10.0.0.1"; .port = "80"; }
backend node2 { .host = "10.0.0.2"; .port = "80"; }
backend node3 { .host = "10.0.0.3"; .port = "80"; }
director cluster random {
{ .backend = node1; .weight = 1; }
{ .backend = node2; .weight = 1; }
{ .backend = node3; .weight = 1; }
sub vcl_init {
new cluster = directors.random();
cluster.add_backend(node1, 1);
cluster.add_backend(node2, 1);
cluster.add_backend(node3, 1);
}
sub vcl_recv {
set req.backend = cluster;
set req.backend = cluster.backend();
}
} -start
......
......@@ -18,19 +18,23 @@ server s2 {
} -start
varnish v1 -vcl {
import directors from "${topbuild}/lib/libvmod_directors/.libs/libvmod_directors.so" ;
backend s1 {
.host = "${s1_addr}"; .port = "${s1_port}";
}
backend s2 {
.host = "${s2_addr}"; .port = "${s2_port}";
}
director foo random {
{ .backend = s2; .weight = 1; }
{ .backend = s1; .weight = 1; }
sub vcl_init {
new foo = directors.random();
foo.add_backend(s1, 1);
foo.add_backend(s2, 1);
}
sub vcl_recv {
set req.backend = foo;
set req.backend = foo.backend();
}
} -start
......
......@@ -6,18 +6,33 @@ server s1 {
} -start
varnish v1 -vcl+backend {
director foo random {
{ .backend = s1; .weight = 1; }
{ .backend = { .host = "${s1_addr}"; .port = "${s1_port}";} .weight =1; }
{ .backend = { .host = "${s1_addr}"; .port = "${s1_port}";} .weight =1; }
import directors from "${topbuild}/lib/libvmod_directors/.libs/libvmod_directors.so" ;
backend b2 {
.host = "${s1_addr}"; .port = "${s1_port}";
}
backend b3 {
.host = "${s1_addr}"; .port = "${s1_port}";
}
sub vcl_init {
new foo = directors.random();
foo.add_backend(s1, 1);
foo.add_backend(b2, 1);
foo.add_backend(b3, 1);
}
sub vcl_recv {
set req.backend = foo;
set req.backend = foo.backend();
}
} -start
varnish v1 -cliok "vcl.list"
varnish v1 -cliok "backend.list"
varnish v1 -vcl+backend { }
varnish v1 -cliok "vcl.list"
varnish v1 -cliok "backend.list"
varnish v1 -cliok "vcl.list"
varnish v1 -cliok "vcl.discard vcl1"
......
......@@ -8,13 +8,16 @@ server s1 {
} -start
varnish v1 -vcl+backend {
director foo random {
{ .backend = s1; .weight = 1; }
{ .weight = 1; .backend = s1; }
import directors from "${topbuild}/lib/libvmod_directors/.libs/libvmod_directors.so";
sub vcl_init {
new foo = directors.random();
foo.add_backend(s1, 1);
foo.add_backend(s1, 1);
}
sub vcl_recv {
set req.backend = foo;
set req.backend = foo.backend();
}
} -start
......
......@@ -32,15 +32,18 @@ server s4 {
} -start
varnish v1 -vcl+backend {
director foo random {
{ .backend = s1; .weight = 1; }
{ .backend = s2; .weight = 1; }
{ .backend = s3; .weight = 1; }
{ .backend = s4; .weight = 1; }
import directors from "${topbuild}/lib/libvmod_directors/.libs/libvmod_directors.so" ;
sub vcl_init {
new foo = directors.random();
foo.add_backend(s1, 1);
foo.add_backend(s2, 1);
foo.add_backend(s3, 1);
foo.add_backend(s4, 1);
}
sub vcl_recv {
set req.backend = foo;
set req.backend = foo.backend();
return(pass);
}
} -start
......
......@@ -17,6 +17,7 @@ libvmod_directors_la_SOURCES = \
vdir.c \
vdir.h \
fall_back.c \
random.c \
round_robin.c
nodist_libvmod_directors_la_SOURCES = \
......
/*-
* Copyright (c) 2013 Varnish Software AS
* All rights reserved.
*
* Author: Poul-Henning Kamp <phk@FreeBSD.org>
*
* 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.
*/
#include "config.h"
#include <math.h>
#include <stdlib.h>
#include "cache/cache.h"
#include "cache/cache_backend.h"
#include "vrt.h"
#include "vbm.h"
#include "vdir.h"
#include "vcc_if.h"
struct vmod_directors_random {
unsigned magic;
#define VMOD_DIRECTORS_RANDOM_MAGIC 0x4732d092
struct vdir *vd;
unsigned nloops;
struct vbitmap *vbm;
};
static unsigned __match_proto__(vdi_healthy)
vmod_rr_healthy(const struct director *dir, const struct req *req)
{
struct vmod_directors_random *rr;
CAST_OBJ_NOTNULL(rr, dir->priv, VMOD_DIRECTORS_RANDOM_MAGIC);
return (vdir_any_healthy(rr->vd, req));
}
static struct vbc * __match_proto__(vdi_getfd_f)
vmod_rr_getfd(const struct director *dir, struct req *req)
{
struct vmod_directors_random *rr;
struct vbitmap *vbm = NULL;
unsigned u, v, l;
VCL_BACKEND be = NULL;
double tw;
int nbe;
double r;
CAST_OBJ_NOTNULL(rr, dir->priv, VMOD_DIRECTORS_RANDOM_MAGIC);
tw = rr->vd->total_weight;
nbe = rr->vd->n_backend;
r = scalbn(random(), -31);
assert(r >= 0.0 && r <= 1.0);
vdir_lock(rr->vd);
for (l = 0; nbe > 0 && tw > 0.0 && l < rr->nloops; l++) {
u = vdir_pick_by_weight(rr->vd, r * tw, vbm);
be = rr->vd->backend[u];
CHECK_OBJ_NOTNULL(be, DIRECTOR_MAGIC);
if (be->healthy(be, req))
break;
if (l == 0) {
vbm = rr->vbm;
for (v = 0; v < nbe; v++)
vbit_clr(vbm, v);
}
vbit_set(vbm, u);
nbe--;
tw -= rr->vd->weight[u];
be = NULL;
}
vdir_unlock(rr->vd);
if (be == NULL)
return (NULL);
return (be->getfd(be, req));
}
VCL_VOID __match_proto__()
vmod_random__init(struct req *req, struct vmod_directors_random **rrp,
const char *vcl_name)
{
struct vmod_directors_random *rr;
AZ(req);
AN(rrp);
AZ(*rrp);
ALLOC_OBJ(rr, VMOD_DIRECTORS_RANDOM_MAGIC);
AN(rr);
rr->vbm = vbit_init(8);
AN(rr->vbm);
rr->nloops = 3; //
*rrp = rr;
vdir_new(&rr->vd, vcl_name, vmod_rr_healthy, vmod_rr_getfd, rr);
}
VCL_VOID __match_proto__()
vmod_random__fini(struct req *req, struct vmod_directors_random **rrp)
{
struct vmod_directors_random *rr;
AZ(req);
rr = *rrp;
*rrp = NULL;
CHECK_OBJ_NOTNULL(rr, VMOD_DIRECTORS_RANDOM_MAGIC);
vdir_delete(&rr->vd);
vbit_destroy(rr->vbm);
FREE_OBJ(rr);
}
VCL_VOID __match_proto__()
vmod_random_add_backend(struct req *req,
struct vmod_directors_random *rr, VCL_BACKEND be, double w)
{
(void)req;
CHECK_OBJ_NOTNULL(rr, VMOD_DIRECTORS_RANDOM_MAGIC);
(void)vdir_add_backend(rr->vd, be, w);
}
VCL_BACKEND __match_proto__()
vmod_random_backend(struct req *req, struct vmod_directors_random *rr)
{
(void)req;
CHECK_OBJ_NOTNULL(rr, VMOD_DIRECTORS_RANDOM_MAGIC);
return (rr->vd->dir);
}
......@@ -34,6 +34,7 @@
#include "cache/cache_backend.h"
#include "vrt.h"
#include "vbm.h"
#include "vdir.h"
......@@ -118,6 +119,7 @@ vdir_add_backend(struct vdir *vd, VCL_BACKEND be, double weight)
u = vd->n_backend++;
vd->backend[u] = be;
vd->weight[u] = weight;
vd->total_weight += weight;
vdir_unlock(vd);
return (u);
}
......@@ -142,3 +144,24 @@ vdir_any_healthy(struct vdir *vd, const struct req *req)
vdir_unlock(vd);
return (retval);
}
unsigned
vdir_pick_by_weight(const struct vdir *vd, double w,
const struct vbitmap *blacklist)
{
double a = 0.0;
VCL_BACKEND be = NULL;
unsigned u;
for (u = 0; u < vd->n_backend; u++) {
be = vd->backend[u];
CHECK_OBJ_NOTNULL(be, DIRECTOR_MAGIC);
if (blacklist != NULL && vbit_test(blacklist, u))
continue;
a += vd->weight[u];
if (w < a)
return (u);
}
WRONG("");
}
......@@ -26,6 +26,8 @@
* SUCH DAMAGE.
*/
struct vbitmap;
struct vdir {
unsigned magic;
#define VDIR_MAGIC 0x99f4b726
......@@ -34,6 +36,7 @@ struct vdir {
unsigned l_backend;
VCL_BACKEND *backend;
double *weight;
double total_weight;
struct director *dir;
};
......@@ -44,3 +47,5 @@ void vdir_lock(struct vdir *vd);
void vdir_unlock(struct vdir *vd);
unsigned vdir_add_backend(struct vdir *vd, VCL_BACKEND be, double weight);
unsigned vdir_any_healthy(struct vdir *vd, const struct req *);
unsigned vdir_pick_by_weight(const struct vdir *vd, double w,
const struct vbitmap *blacklist);
......@@ -36,3 +36,8 @@ Object fallback() {
Method VOID .add_backend(BACKEND)
Method BACKEND .backend()
}
Object random() {
Method VOID .add_backend(BACKEND, REAL)
Method BACKEND .backend()
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment