[PATCH] Improved hash director behavior
WaveCDN Development
dev at wavecdn.com
Mon Mar 12 16:21:28 CET 2012
This patch improves the behavior of the hash director when some of its
backends get unhealty. The hash range of each unhealthy backend is
splitted and mapped to the remaining healthy backends. Thus, not the
complete hash range is beeing remapped and backends will perform better.
---
bin/varnishd/cache/cache_dir_random.c | 75
++++++++++++++++++++++++++++++++-
1 files changed, 74 insertions(+), 1 deletions(-)
diff --git a/bin/varnishd/cache/cache_dir_random.c
b/bin/varnishd/cache/cache_dir_random.c
index b323343..a7ae4e0 100644
--- a/bin/varnishd/cache/cache_dir_random.c
+++ b/bin/varnishd/cache/cache_dir_random.c
@@ -125,6 +125,7 @@ vdi_random_init_seed(const struct vdi_random *vs,
const struct sess *sp)
/*
* Find the healthy backend corresponding to the weight r [0...1[
+ * except for the hash director.
*/
static struct vbc *
vdi_random_pick_one(struct sess *sp, const struct vdi_random *vs,
double r)
@@ -158,6 +159,75 @@ vdi_random_pick_one(struct sess *sp, const struct
vdi_random *vs, double r)
}
/*
+ * Find the healthy backend corresponding to the weight r [0...1[
+ * for the hash director. When a backend becomes unhealthy, its hash
+ * range is splitted and mapped to the remaining healthy backends.
+ */
+static struct vbc *
+vdi_random_hash_pick_one(struct sess *sp, const struct vdi_random *vs,
double r)
+{
+ int nhealthy;
+ int healthy[vs->nhosts];
+ int i, j;
+ double s1;
+
+ assert(r >= 0.0 && r < 1.0);
+
+ /*
+ * Get the number of healthy hosts, sum up weights,
+ * initialize array w with host weights and
+ * build arry with indizes of healthy hosts.
+ */
+ nhealthy = 0;
+ s1 = 0.0;
+ for (i = 0; i < vs->nhosts; i++) {
+ if (VDI_Healthy(vs->hosts[i].backend, sp))
+ {
+ healthy[i] = 1;
+ nhealthy++;
+ }
+ else
+ {
+ healthy[i] = 0;
+ }
+ s1 += vs->hosts[i].weight;
+ }
+ if (nhealthy == 0)
+ return (NULL);
+
+ /* Pick host */
+ r *= s1;
+ s1 = 0.0;
+ for (i = 0; i < vs->nhosts; i++) {
+ if (healthy[i] == 1)
+ {
+ s1 += vs->hosts[i].weight;
+ if (r < s1)
+ {
+ return(VDI_GetFd(vs->hosts[i].backend, sp));
+ }
+ }
+ else
+ {
+ /* Host unhealthy, split his weight to healthy hosts */
+ double part = vs->hosts[i].weight / nhealthy;
+ for (j = 0; j < vs->nhosts; j++) {
+ if(healthy[j] == 1)
+ {
+ s1 += part;
+ if (r < s1)
+ {
+ return(VDI_GetFd(vs->hosts[healthy[j]].backend, sp));
+ }
+ }
+ }
+ }
+ }
+ return (NULL);
+}
+
+
+/*
* Try the specified number of times to get a backend.
* First one according to policy, after that, deterministically
* random by rehashing the key.
@@ -177,7 +247,10 @@ 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(vs->criteria == c_hash)
+ vbe = vdi_random_hash_pick_one(sp, vs, r);
+ else
+ vbe = vdi_random_pick_one(sp, vs, r);
if (vbe != NULL)
return (vbe);
r = vdi_random_sha((void *)&r, sizeof(r));
--
1.7.2.5
More information about the varnish-dev
mailing list