当后端出现问题时,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