当后端出现问题时,Varnish hash director 如何处理密钥分配?
How does Varnish hash director handle key distribution when a backend is sick?
Varnish vmod_directors 启用不同模式的后端负载平衡:round_robin、回退、随机和 HASH。对于第一个很清楚 Varnish 将如何处理有问题的后端。
但是 HASH 导向器中会发生什么?它会重新分配所有的密钥space?或者只有 1/N 个键会被移动(N 是后端的数量)?
或者您决定将后端分组为 2 对以实现高可用性并且不重复缓存? (导演可以使用其他导演作为后端)
sub vcl_init {
new h = directors.hash();
h.add_backend(backend_1, 1);
h.add_backend(backend_2, 1); // <------ sick
h.add_backend(backend_3, 1);
h.add_backend(backend_4, 1);
h.add_backend(backend_5, 1);
h.add_backend(backend_6, 1);
}
sub vcl_recv {
// pick a backend based on the request URL
set req.backend_hint = h.backend(req.url);
}
VS
new main_hash_director = directors.hash();
h.add_backend(hash_director_A, 1);
h.add_backend(hash_director_B, 1);
h.add_backend(hash_director_C, 1);
new hash_director_A = directors.hash();
h.add_backend(backend_1, 1);
h.add_backend(backend_2, 1); // <------ sick
new hash_director_B = directors.hash();
h.add_backend(backend_3, 1);
h.add_backend(backend_4, 1);
new hash_director_C = directors.hash();
h.add_backend(backend_5, 1);
h.add_backend(backend_6, 1);
我做了一个清漆测试,看看到底发生了什么,清漆重新分配当前健康后端上的所有密钥。
有一个 VMOD 可用于一致性哈希:https://www.varnish-cache.org/vmod/vslp-stateless-persistence-consistent-hashing-director-vmod
清漆测试"Hash director"
server s1 {
rxreq
txresp -hdr "Foo: 1"
rxreq
txresp -hdr "Foo: 1"
rxreq
txresp -hdr "Foo: 1"
rxreq
txresp -hdr "Foo: 1"
} -start
server s2 {
rxreq
txresp -hdr "Foo: 2"
rxreq
txresp -hdr "Foo: 2"
rxreq
txresp -hdr "Foo: 2"
rxreq
txresp -hdr "Foo: 2"
} -start
server s3 {
rxreq
txresp -hdr "Foo: 3"
rxreq
txresp -hdr "Foo: 3"
rxreq
txresp -hdr "Foo: 3"
rxreq
txresp -hdr "Foo: 3"
} -start
server s4 {
rxreq
txresp -hdr "Foo: 4"
rxreq
txresp -hdr "Foo: 4"
rxreq
txresp -hdr "Foo: 4"
rxreq
txresp -hdr "Foo: 4"
} -start
server s5 {
rxreq
txresp -hdr "Foo: 5"
rxreq
txresp -hdr "Foo: 5"
rxreq
txresp -hdr "Foo: 5"
rxreq
txresp -hdr "Foo: 5"
} -start
server s6 {
rxreq
txresp -hdr "Foo: 6"
rxreq
txresp -hdr "Foo: 6"
rxreq
txresp -hdr "Foo: 6"
rxreq
txresp -hdr "Foo: 6"
} -start
server s7 {
rxreq
txresp -hdr "Foo: 7"
rxreq
txresp -hdr "Foo: 7"
rxreq
txresp -hdr "Foo: 7"
rxreq
txresp -hdr "Foo: 7"
} -start
server s8 {
rxreq
txresp -hdr "Foo: 8"
rxreq
txresp -hdr "Foo: 8"
rxreq
txresp -hdr "Foo: 8"
rxreq
txresp -hdr "Foo: 8"
} -start
server s9 {
rxreq
txresp -hdr "Foo: 9"
rxreq
txresp -hdr "Foo: 9"
rxreq
txresp -hdr "Foo: 9"
rxreq
txresp -hdr "Foo: 9"
} -start
server s10 {
rxreq
txresp -hdr "Foo: 10"
rxreq
txresp -hdr "Foo: 10"
rxreq
txresp -hdr "Foo: 10"
rxreq
txresp -hdr "Foo: 10"
} -start
varnish v1 -vcl+backend {
director h1 hash {
{ .backend = s1; .weight = 1; }
{ .backend = s2; .weight = 1; }
{ .backend = s3; .weight = 1; }
{ .backend = s4; .weight = 1; }
{ .backend = s5; .weight = 1; }
{ .backend = s6; .weight = 1; }
{ .backend = s7; .weight = 1; }
{ .backend = s8; .weight = 1; }
{ .backend = s9; .weight = 1; }
{ .backend = s10; .weight = 1; }
}
sub vcl_recv {
set req.backend = h1;
return(pass);
}
} -start
# first run-----------------------------
client c1 {
txreq -url /12
rxresp
expect resp.http.foo == "1"
txreq -url /14
rxresp
expect resp.http.foo == "4"
txreq -url /45
rxresp
expect resp.http.foo == "7"
txreq -url /65
rxresp
expect resp.http.foo == "5"
txreq -url /78
rxresp
expect resp.http.foo == "9"
txreq -url /894
rxresp
expect resp.http.foo == "8"
txreq -url /115
rxresp
expect resp.http.foo == "2"
txreq -url /321341
rxresp
expect resp.http.foo == "6"
txreq -url /612
rxresp
expect resp.http.foo == "10"
txreq -url /33
rxresp
expect resp.http.foo == "3"
} -run
varnish v1 -cliok "backend.set_health s1 sick"
# second run-----------------------------
client c1 {
txreq -url /12
rxresp
# expect resp.http.foo == "1" FAIL
txreq -url /14
rxresp
expect resp.http.foo == "4"
txreq -url /45
rxresp
# expect resp.http.foo == "7" FAIL
txreq -url /65
rxresp
expect resp.http.foo == "5"
txreq -url /78
rxresp
# expect resp.http.foo == "9" FAIL
txreq -url /894
rxresp
expect resp.http.foo == "8"
txreq -url /115
rxresp
expect resp.http.foo == "2"
txreq -url /321341
rxresp
expect resp.http.foo == "6"
txreq -url /612
rxresp
# expect resp.http.foo == "10" FAIL
txreq -url /33
rxresp
expect resp.http.foo == "3"
} -run
Varnish vmod_directors 启用不同模式的后端负载平衡:round_robin、回退、随机和 HASH。对于第一个很清楚 Varnish 将如何处理有问题的后端。
但是 HASH 导向器中会发生什么?它会重新分配所有的密钥space?或者只有 1/N 个键会被移动(N 是后端的数量)?
或者您决定将后端分组为 2 对以实现高可用性并且不重复缓存? (导演可以使用其他导演作为后端)
sub vcl_init {
new h = directors.hash();
h.add_backend(backend_1, 1);
h.add_backend(backend_2, 1); // <------ sick
h.add_backend(backend_3, 1);
h.add_backend(backend_4, 1);
h.add_backend(backend_5, 1);
h.add_backend(backend_6, 1);
}
sub vcl_recv {
// pick a backend based on the request URL
set req.backend_hint = h.backend(req.url);
}
VS
new main_hash_director = directors.hash();
h.add_backend(hash_director_A, 1);
h.add_backend(hash_director_B, 1);
h.add_backend(hash_director_C, 1);
new hash_director_A = directors.hash();
h.add_backend(backend_1, 1);
h.add_backend(backend_2, 1); // <------ sick
new hash_director_B = directors.hash();
h.add_backend(backend_3, 1);
h.add_backend(backend_4, 1);
new hash_director_C = directors.hash();
h.add_backend(backend_5, 1);
h.add_backend(backend_6, 1);
我做了一个清漆测试,看看到底发生了什么,清漆重新分配当前健康后端上的所有密钥。
有一个 VMOD 可用于一致性哈希:https://www.varnish-cache.org/vmod/vslp-stateless-persistence-consistent-hashing-director-vmod
清漆测试"Hash director"
server s1 {
rxreq
txresp -hdr "Foo: 1"
rxreq
txresp -hdr "Foo: 1"
rxreq
txresp -hdr "Foo: 1"
rxreq
txresp -hdr "Foo: 1"
} -start
server s2 {
rxreq
txresp -hdr "Foo: 2"
rxreq
txresp -hdr "Foo: 2"
rxreq
txresp -hdr "Foo: 2"
rxreq
txresp -hdr "Foo: 2"
} -start
server s3 {
rxreq
txresp -hdr "Foo: 3"
rxreq
txresp -hdr "Foo: 3"
rxreq
txresp -hdr "Foo: 3"
rxreq
txresp -hdr "Foo: 3"
} -start
server s4 {
rxreq
txresp -hdr "Foo: 4"
rxreq
txresp -hdr "Foo: 4"
rxreq
txresp -hdr "Foo: 4"
rxreq
txresp -hdr "Foo: 4"
} -start
server s5 {
rxreq
txresp -hdr "Foo: 5"
rxreq
txresp -hdr "Foo: 5"
rxreq
txresp -hdr "Foo: 5"
rxreq
txresp -hdr "Foo: 5"
} -start
server s6 {
rxreq
txresp -hdr "Foo: 6"
rxreq
txresp -hdr "Foo: 6"
rxreq
txresp -hdr "Foo: 6"
rxreq
txresp -hdr "Foo: 6"
} -start
server s7 {
rxreq
txresp -hdr "Foo: 7"
rxreq
txresp -hdr "Foo: 7"
rxreq
txresp -hdr "Foo: 7"
rxreq
txresp -hdr "Foo: 7"
} -start
server s8 {
rxreq
txresp -hdr "Foo: 8"
rxreq
txresp -hdr "Foo: 8"
rxreq
txresp -hdr "Foo: 8"
rxreq
txresp -hdr "Foo: 8"
} -start
server s9 {
rxreq
txresp -hdr "Foo: 9"
rxreq
txresp -hdr "Foo: 9"
rxreq
txresp -hdr "Foo: 9"
rxreq
txresp -hdr "Foo: 9"
} -start
server s10 {
rxreq
txresp -hdr "Foo: 10"
rxreq
txresp -hdr "Foo: 10"
rxreq
txresp -hdr "Foo: 10"
rxreq
txresp -hdr "Foo: 10"
} -start
varnish v1 -vcl+backend {
director h1 hash {
{ .backend = s1; .weight = 1; }
{ .backend = s2; .weight = 1; }
{ .backend = s3; .weight = 1; }
{ .backend = s4; .weight = 1; }
{ .backend = s5; .weight = 1; }
{ .backend = s6; .weight = 1; }
{ .backend = s7; .weight = 1; }
{ .backend = s8; .weight = 1; }
{ .backend = s9; .weight = 1; }
{ .backend = s10; .weight = 1; }
}
sub vcl_recv {
set req.backend = h1;
return(pass);
}
} -start
# first run-----------------------------
client c1 {
txreq -url /12
rxresp
expect resp.http.foo == "1"
txreq -url /14
rxresp
expect resp.http.foo == "4"
txreq -url /45
rxresp
expect resp.http.foo == "7"
txreq -url /65
rxresp
expect resp.http.foo == "5"
txreq -url /78
rxresp
expect resp.http.foo == "9"
txreq -url /894
rxresp
expect resp.http.foo == "8"
txreq -url /115
rxresp
expect resp.http.foo == "2"
txreq -url /321341
rxresp
expect resp.http.foo == "6"
txreq -url /612
rxresp
expect resp.http.foo == "10"
txreq -url /33
rxresp
expect resp.http.foo == "3"
} -run
varnish v1 -cliok "backend.set_health s1 sick"
# second run-----------------------------
client c1 {
txreq -url /12
rxresp
# expect resp.http.foo == "1" FAIL
txreq -url /14
rxresp
expect resp.http.foo == "4"
txreq -url /45
rxresp
# expect resp.http.foo == "7" FAIL
txreq -url /65
rxresp
expect resp.http.foo == "5"
txreq -url /78
rxresp
# expect resp.http.foo == "9" FAIL
txreq -url /894
rxresp
expect resp.http.foo == "8"
txreq -url /115
rxresp
expect resp.http.foo == "2"
txreq -url /321341
rxresp
expect resp.http.foo == "6"
txreq -url /612
rxresp
# expect resp.http.foo == "10" FAIL
txreq -url /33
rxresp
expect resp.http.foo == "3"
} -run