Commit 6032765e authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

Experimental "client" director, which chooses backend based on

client-ip.

This does _not_ take X-Forwarded-For: into account.

Feedback welcome.



git-svn-id: http://www.varnish-cache.org/svn/trunk/varnish-cache@4460 d4fa192b-c00b-0410-8231-f00ffab90ce4
parent 871b6b48
...@@ -160,3 +160,4 @@ dir_init_f VRT_init_dir_simple; ...@@ -160,3 +160,4 @@ dir_init_f VRT_init_dir_simple;
dir_init_f VRT_init_dir_hash; dir_init_f VRT_init_dir_hash;
dir_init_f VRT_init_dir_random; dir_init_f VRT_init_dir_random;
dir_init_f VRT_init_dir_round_robin; dir_init_f VRT_init_dir_round_robin;
dir_init_f VRT_init_dir_client;
...@@ -275,6 +275,8 @@ VRT_init_dir(struct cli *cli, struct director **dir, const char *name, ...@@ -275,6 +275,8 @@ VRT_init_dir(struct cli *cli, struct director **dir, const char *name,
VRT_init_dir_random(cli, dir, idx, priv); VRT_init_dir_random(cli, dir, idx, priv);
else if (!strcmp(name, "round-robin")) else if (!strcmp(name, "round-robin"))
VRT_init_dir_round_robin(cli, dir, idx, priv); VRT_init_dir_round_robin(cli, dir, idx, priv);
else if (!strcmp(name, "client"))
VRT_init_dir_client(cli, dir, idx, priv);
else else
INCOMPL(); INCOMPL();
} }
......
...@@ -57,6 +57,7 @@ SVNID("$Id$") ...@@ -57,6 +57,7 @@ SVNID("$Id$")
#include "cache.h" #include "cache.h"
#include "cache_backend.h" #include "cache_backend.h"
#include "vrt.h" #include "vrt.h"
#include "vsha256.h"
/*--------------------------------------------------------------------*/ /*--------------------------------------------------------------------*/
...@@ -65,12 +66,14 @@ struct vdi_random_host { ...@@ -65,12 +66,14 @@ struct vdi_random_host {
double weight; double weight;
}; };
enum crit_e {c_random, c_hash, c_client};
struct vdi_random { struct vdi_random {
unsigned magic; unsigned magic;
#define VDI_RANDOM_MAGIC 0x3771ae23 #define VDI_RANDOM_MAGIC 0x3771ae23
struct director dir; struct director dir;
unsigned use_hash; enum crit_e criteria;
unsigned retries; unsigned retries;
double tot_weight; double tot_weight;
struct vdi_random_host *hosts; struct vdi_random_host *hosts;
...@@ -86,22 +89,47 @@ vdi_random_getfd(const struct director *d, struct sess *sp) ...@@ -86,22 +89,47 @@ vdi_random_getfd(const struct director *d, struct sess *sp)
unsigned u; unsigned u;
struct vbe_conn *vbe; struct vbe_conn *vbe;
struct director *d2; struct director *d2;
struct SHA256Context ctx;
unsigned char sign[SHA256_LEN], *hp;
CHECK_OBJ_NOTNULL(sp, SESS_MAGIC); CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
CHECK_OBJ_NOTNULL(d, DIRECTOR_MAGIC); CHECK_OBJ_NOTNULL(d, DIRECTOR_MAGIC);
CAST_OBJ_NOTNULL(vs, d->priv, VDI_RANDOM_MAGIC); CAST_OBJ_NOTNULL(vs, d->priv, VDI_RANDOM_MAGIC);
if (vs->criteria == c_client) {
/*
* Hash the client IP# ascii representation, rather than
* rely on the raw IP# being a good hash distributor, since
* experience shows this not to be the case.
* We do not hash the port number, to make everybody behind
* a given NAT gateway fetch from the same backend.
*/
SHA256_Init(&ctx);
AN(sp->addr);
SHA256_Update(&ctx, sp->addr, strlen(sp->addr));
SHA256_Final(sign, &ctx);
hp = sign;
}
if (vs->criteria == c_hash) {
/*
* Reuse the hash-string, the objective here is to fetch the
* same object on the same backend all the time
*/
hp = sp->digest;
}
/* /*
* If we are hashing, first try to hit our "canonical backend" * If we are hashing, first try to hit our "canonical backend"
* If that fails, we fall through, and select a weighted backend * If that fails, we fall through, and select a weighted backend
* amongst the good set. * amongst the healthy set.
*/ */
if (vs->use_hash) { if (vs->criteria != c_random) {
u = sp->digest[3] << 24; u = hp[3] << 24;
u |= sp->digest[2] << 16; u |= hp[2] << 16;
u |= sp->digest[1] << 8; u |= hp[1] << 8;
u |= sp->digest[0] << 0; u |= hp[0] << 0;
r = u / 4294967296.0; r = u / 4294967296.0;
assert(r >= 0.0 && r < 1.0);
r *= vs->tot_weight; r *= vs->tot_weight;
s1 = 0.0; s1 = 0.0;
for (i = 0; i < vs->nhosts; i++) { for (i = 0; i < vs->nhosts; i++) {
...@@ -119,7 +147,6 @@ vdi_random_getfd(const struct director *d, struct sess *sp) ...@@ -119,7 +147,6 @@ vdi_random_getfd(const struct director *d, struct sess *sp)
} }
for (k = 0; k < vs->retries; ) { for (k = 0; k < vs->retries; ) {
/* Sum up the weights of healty backends */ /* Sum up the weights of healty backends */
s1 = 0.0; s1 = 0.0;
for (i = 0; i < vs->nhosts; i++) { for (i = 0; i < vs->nhosts; i++) {
...@@ -132,11 +159,7 @@ vdi_random_getfd(const struct director *d, struct sess *sp) ...@@ -132,11 +159,7 @@ vdi_random_getfd(const struct director *d, struct sess *sp)
if (s1 == 0.0) if (s1 == 0.0)
return (NULL); return (NULL);
if (vs->use_hash) { if (vs->criteria != c_random) {
u = sp->digest[3] << 24;
u |= sp->digest[2] << 16;
u |= sp->digest[1] << 8;
u |= sp->digest[0] << 0;
r = u / 4294967296.0; r = u / 4294967296.0;
} else { } else {
/* Pick a random threshold in that interval */ /* Pick a random threshold in that interval */
...@@ -197,7 +220,7 @@ vdi_random_fini(struct director *d) ...@@ -197,7 +220,7 @@ vdi_random_fini(struct director *d)
static void static void
vrt_init(struct cli *cli, struct director **bp, int idx, vrt_init(struct cli *cli, struct director **bp, int idx,
const void *priv, int use_hash) const void *priv, enum crit_e criteria)
{ {
const struct vrt_dir_random *t; const struct vrt_dir_random *t;
struct vdi_random *vs; struct vdi_random *vs;
...@@ -222,7 +245,7 @@ vrt_init(struct cli *cli, struct director **bp, int idx, ...@@ -222,7 +245,7 @@ vrt_init(struct cli *cli, struct director **bp, int idx,
vs->dir.fini = vdi_random_fini; vs->dir.fini = vdi_random_fini;
vs->dir.healthy = vdi_random_healthy; vs->dir.healthy = vdi_random_healthy;
vs->use_hash = use_hash; vs->criteria = criteria;
vs->retries = t->retries; vs->retries = t->retries;
if (vs->retries == 0) if (vs->retries == 0)
vs->retries = t->nmember; vs->retries = t->nmember;
...@@ -244,12 +267,19 @@ void ...@@ -244,12 +267,19 @@ void
VRT_init_dir_random(struct cli *cli, struct director **bp, int idx, VRT_init_dir_random(struct cli *cli, struct director **bp, int idx,
const void *priv) const void *priv)
{ {
vrt_init(cli, bp, idx, priv, 0); vrt_init(cli, bp, idx, priv, c_random);
} }
void void
VRT_init_dir_hash(struct cli *cli, struct director **bp, int idx, VRT_init_dir_hash(struct cli *cli, struct director **bp, int idx,
const void *priv) const void *priv)
{ {
vrt_init(cli, bp, idx, priv, 1); vrt_init(cli, bp, idx, priv, c_hash);
}
void
VRT_init_dir_client(struct cli *cli, struct director **bp, int idx,
const void *priv)
{
vrt_init(cli, bp, idx, priv, c_client);
} }
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