
fgsch at lodoss
Feb 14, 2012, 5:27 PM
Post #2 of 5
(252 views)
Permalink
|
|
Re: [PATCH] add a least-connection director
[In reply to]
|
|
On Sat, 21 Jan 2012 10:14:27 +0000 "Federico G. Schwindt" <fgsch [at] lodoss> wrote: > Hi, > > The diff below adds a least-connection director based on the random director. > Documentation and tests included. > Comments? OKs? Updated diff against trunk. Anyone? bin/varnishd/cache/cache_backend.h | 1 + bin/varnishd/cache/cache_backend_cfg.c | 2 + bin/varnishd/cache/cache_dir_random.c | 52 ++++++++++++++++++-- bin/varnishtest/tests/v00038.vtc | 86 ++++++++++++++++++++++++++++++++ doc/sphinx/reference/vcl.rst | 11 ++++ lib/libvcl/vcc_backend.c | 1 + 6 files changed, 149 insertions(+), 4 deletions(-) diff --git a/bin/varnishd/cache/cache_backend.h b/bin/varnishd/cache/cache_backend.h index b1688f9..82f32c2 100644 --- a/bin/varnishd/cache/cache_backend.h +++ b/bin/varnishd/cache/cache_backend.h @@ -192,3 +192,4 @@ dir_init_f VRT_init_dir_random; dir_init_f VRT_init_dir_round_robin; dir_init_f VRT_init_dir_fallback; dir_init_f VRT_init_dir_client; +dir_init_f VRT_init_dir_least_connection; diff --git a/bin/varnishd/cache/cache_backend_cfg.c b/bin/varnishd/cache/cache_backend_cfg.c index c2d022d..9bed6ed 100644 --- a/bin/varnishd/cache/cache_backend_cfg.c +++ b/bin/varnishd/cache/cache_backend_cfg.c @@ -263,6 +263,8 @@ VRT_init_dir(struct cli *cli, struct director **dir, const char *name, VRT_init_dir_fallback(cli, dir, idx, priv); else if (!strcmp(name, "client")) VRT_init_dir_client(cli, dir, idx, priv); + else if (!strcmp(name, "least-connection")) + VRT_init_dir_least_connection(cli, dir, idx, priv); else INCOMPL(); } diff --git a/bin/varnishd/cache/cache_dir_random.c b/bin/varnishd/cache/cache_dir_random.c index b323343..7cd0708 100644 --- a/bin/varnishd/cache/cache_dir_random.c +++ b/bin/varnishd/cache/cache_dir_random.c @@ -26,8 +26,9 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * This code is shared between the random, client and hash directors, because - * they share the same properties and most of the same selection logic. + * This code is shared between the random, client, hash and least-connection + * directors, because they share the same properties and most of the same + * selection logic. * * The random director picks a backend on random. * @@ -35,6 +36,9 @@ * * The client director picks based on client identity or IP-address * + * The least-connection director picks a backend with the least number of + * established connections. + * * In all cases, the choice is by weight of the healthy subset of * configured backends. * @@ -63,7 +67,7 @@ struct vdi_random_host { double weight; }; -enum crit_e {c_random, c_hash, c_client}; +enum crit_e {c_random, c_hash, c_client, c_least_connection}; struct vdi_random { unsigned magic; @@ -185,6 +189,36 @@ vdi_random_getfd(const struct director *d, struct sess *sp) return (NULL); } +static struct vbc * +vdi_least_connection_getfd(const struct director *d, struct sess *sp) +{ + int i, m; + struct vdi_random *vs; + struct backend *bi, *bm; + + CHECK_OBJ_NOTNULL(sp, SESS_MAGIC); + CHECK_OBJ_NOTNULL(d, DIRECTOR_MAGIC); + CAST_OBJ_NOTNULL(vs, d->priv, VDI_RANDOM_MAGIC); + + for (m = 0; m < vs->nhosts; m++) { + if (!VDI_Healthy(vs->hosts[m].backend, sp)) + continue; + bm = vdi_get_backend_if_simple(vs->hosts[m].backend); + for (i = m + 1; i < vs->nhosts; i++) { + if (!VDI_Healthy(vs->hosts[i].backend, sp)) + continue; + bi = vdi_get_backend_if_simple(vs->hosts[i].backend); + if (bm->refcount * vs->hosts[i].weight > + bi->refcount * vs->hosts[m].weight) { + bm = bi; + m = i; + } + } + return (VDI_GetFd(vs->hosts[m].backend, sp)); + } + return (NULL); +} + /* * Healthy if just a single backend is... */ @@ -241,7 +275,10 @@ vrt_init(struct cli *cli, struct director **bp, int idx, vs->dir.priv = vs; vs->dir.name = "random"; REPLACE(vs->dir.vcl_name, t->name); - vs->dir.getfd = vdi_random_getfd; + if (criteria == c_least_connection) + vs->dir.getfd = vdi_least_connection_getfd; + else + vs->dir.getfd = vdi_random_getfd; vs->dir.fini = vdi_random_fini; vs->dir.healthy = vdi_random_healthy; @@ -283,3 +320,10 @@ VRT_init_dir_client(struct cli *cli, struct director **bp, int idx, { vrt_init(cli, bp, idx, priv, c_client); } + +void +VRT_init_dir_least_connection(struct cli *cli, struct director **bp, int idx, + const void *priv) +{ + vrt_init(cli, bp, idx, priv, c_least_connection); +} diff --git a/bin/varnishtest/tests/v00038.vtc b/bin/varnishtest/tests/v00038.vtc new file mode 100644 index 0000000..f392f6f --- /dev/null +++ b/bin/varnishtest/tests/v00038.vtc @@ -0,0 +1,86 @@ +varnishtest "Test least-connection director" + +server s1 { + rxreq + sema r1 sync 3 + sema r1 sync 2 + txresp -hdr "be: s1" + close + + accept + rxreq + txresp -hdr "be: s1" +} -start + +server s2 { + rxreq + sema r1 sync 3 + txresp -hdr "be: s2" + close + + accept + rxreq + txresp -hdr "be: s2" +} -start + +server s3 { + rxreq + txresp -hdr "be: s3" + close + + accept + rxreq + txresp -hdr "be: s3" +} -start + +varnish v1 -vcl+backend { + director lc least-connection { + { .backend = s1; .weight = 1; } + { .backend = s2; .weight = 1; } + { .backend = s3; .weight = 1; } + } + sub vcl_recv { + set req.backend = lc; + return (pass); + } +} -start + +client c1 { + txreq + rxresp + expect resp.status == 200 +} -start + +client c2 { + txreq + rxresp + expect resp.status == 200 +} -start + +delay .5 + +client c3 { + txreq + rxresp + expect resp.status == 200 + + txreq + rxresp + expect resp.http.be == "s3" + + sema r1 sync 3 + + txreq + rxresp + expect resp.http.be == "s2" + + sema r1 sync 2 + + txreq + rxresp + expect resp.http.be == "s1" +} -start + +client c1 -wait +client c2 -wait +client c3 -wait diff --git a/doc/sphinx/reference/vcl.rst b/doc/sphinx/reference/vcl.rst index 1ef14d6..373e6f8 100644 --- a/doc/sphinx/reference/vcl.rst +++ b/doc/sphinx/reference/vcl.rst @@ -275,6 +275,17 @@ An example of a fallback director:: // are unhealthy. } +The least-connection director +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The least-connection director will pick a backend with the least number of +established connections. + +Each backend requires a .weight option which sets the amount of traffic +each backend will get compared to the others. Equal weight means equal +traffic. A backend with lower weight than an other will get proportionally +less traffic. + Backend probes -------------- diff --git a/lib/libvcl/vcc_backend.c b/lib/libvcl/vcc_backend.c index fb160e7..d1a8a31 100644 --- a/lib/libvcl/vcc_backend.c +++ b/lib/libvcl/vcc_backend.c @@ -688,6 +688,7 @@ static const struct dirlist { { "hash", vcc_ParseRandomDirector }, { "random", vcc_ParseRandomDirector }, { "client", vcc_ParseRandomDirector }, + { "least-connection", vcc_ParseRandomDirector }, { "round-robin", vcc_ParseRoundRobinDirector }, { "fallback", vcc_ParseRoundRobinDirector }, { "dns", vcc_ParseDnsDirector }, _______________________________________________ varnish-dev mailing list varnish-dev [at] varnish-cache https://www.varnish-cache.org/lists/mailman/listinfo/varnish-dev
|