[master] 0352ea2 Make the random/hash/client director use a stable hash.
Poul-Henning Kamp
phk at varnish-cache.org
Thu May 10 11:24:52 CEST 2012
commit 0352ea2567c5b4df803635ec8ac4288ae5c0fa07
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date: Thu May 10 09:20:54 2012 +0000
Make the random/hash/client director use a stable hash.
If the chosen backend is sick or fails to give us a connection,
we rescale the keys position in the backends window onto the
all the remaining backends.
The upside of this is that we get a stable and predicatable
hash distribution.
The downside of this is that you are very unlikely to spot the
healthy .weight=1 backend between two .weight=100 sick ones before
your retries run out.
Inspired by: patch from WaveCDN
diff --git a/bin/varnishd/cache/cache_dir_random.c b/bin/varnishd/cache/cache_dir_random.c
index b323343..8a0bcd2 100644
--- a/bin/varnishd/cache/cache_dir_random.c
+++ b/bin/varnishd/cache/cache_dir_random.c
@@ -127,32 +127,50 @@ vdi_random_init_seed(const struct vdi_random *vs, const struct sess *sp)
* Find the healthy backend corresponding to the weight r [0...1[
*/
static struct vbc *
-vdi_random_pick_one(struct sess *sp, const struct vdi_random *vs, double r)
+vdi_random_pick_one(struct sess *sp, const struct vdi_random *vs, double r,
+ int retries)
{
double w[vs->nhosts];
int i;
- double s1;
-
- assert(r >= 0.0 && r < 1.0);
+ double s1, s2;
+ struct vbc *vbc;
+ /* Sum up the weights of all backends */
memset(w, 0, sizeof w);
- /* Sum up the weights of healty backends */
s1 = 0.0;
for (i = 0; i < vs->nhosts; i++) {
- if (VDI_Healthy(vs->hosts[i].backend, sp))
- w[i] = vs->hosts[i].weight;
+ w[i] = vs->hosts[i].weight;
s1 += w[i];
}
-
if (s1 == 0.0)
return (NULL);
- r *= s1;
- s1 = 0.0;
- for (i = 0; i < vs->nhosts; i++) {
- s1 += w[i];
- if (r < s1)
- return(VDI_GetFd(vs->hosts[i].backend, sp));
+ while (retries-- > 0) {
+ assert(r >= 0.0 && r < 1.0);
+
+ r *= s1;
+ s2 = 0.0;
+ for (i = 0; i < vs->nhosts; i++) {
+ s2 += w[i];
+ if (r >= s2)
+ continue;
+ if (!VDI_Healthy(vs->hosts[i].backend, sp))
+ break;
+ vbc = VDI_GetFd(vs->hosts[i].backend, sp);
+ if (vbc == NULL)
+ break;
+ return (vbc);
+ }
+ /*
+ * Rescale and rotate r's relative position this backends
+ * window onto the remaining backends and try again.
+ */
+ r -= (s2 - w[i]); // r in [0...w[i][
+ r /= w[i]; // r in [0...1[
+ r *= (s1 - w[i])/s1; // r in [0...1-W[i]]
+ r += s2 / s1; // rotate
+ if (r >= 1.0)
+ r -= 1.0;
}
return (NULL);
}
@@ -165,10 +183,8 @@ vdi_random_pick_one(struct sess *sp, const struct vdi_random *vs, double r)
static struct vbc *
vdi_random_getfd(const struct director *d, struct sess *sp)
{
- int k;
struct vdi_random *vs;
double r;
- struct vbc *vbe;
CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
CHECK_OBJ_NOTNULL(d, DIRECTOR_MAGIC);
@@ -176,17 +192,12 @@ vdi_random_getfd(const struct director *d, struct sess *sp)
r = vdi_random_init_seed(vs, sp);
- for (k = 0; k < vs->retries; k++) {
- vbe = vdi_random_pick_one(sp, vs, r);
- if (vbe != NULL)
- return (vbe);
- r = vdi_random_sha((void *)&r, sizeof(r));
- }
- return (NULL);
+ return (vdi_random_pick_one(sp, vs, r, vs->retries));
}
/*
* Healthy if just a single backend is...
+ * XXX: we should really have a weight param/criteria here
*/
static unsigned
vdi_random_healthy(const struct director *d, const struct sess *sp)
More information about the varnish-commit
mailing list