Varnish 通过重写每个服务器的请求实现负载平衡

Varnish 通过重写每个服务器的请求实现负载平衡

我正在尝试使用 Varnish 对第三方 Web 应用程序进行负载平衡,并且该第三方应用程序需要“真实”的服务器名称(它似乎在后台通过名称连接到该服务器(并且 localhost 不起作用:()在查询字符串中传递。我还需要故障转移,这意味着我想使用导向器,以便我的配置可以简单并且可扩展。

下面是我所举的一个基本例子喜欢去做:

sub vcl_pass {
  set bereq.http.X-Varnish-Backend = bereq.backend.name
}

但是 backend.name 只有在我们发出请求后才在 beresp 中可用。看来 Varnish 直到vcl_pass 完成,并且在请求发送到后端之前没有其他钩子。

这是正确的吗?如果是这样,还有其他解决方案吗(除了在我无法控制的 Web 服务器上修复它)?如果没有循环,即使我在 VCL 中实现了替换客户端控制器,它也无法扩展到几台服务器之外。

答案1

首先,您必须制定一个策略来区分所使用的应用程序。您可以使用不同的主机名(它们都指向您的 Varnish 代理服务器),也可以使用不同的 URL 来决定哪个请求应该由哪个后端系统处理。如果您有策略,请设置您的 Varnish:

示例 A)不同的主机名

准备所有必需的后端。它可以是单个服务器,也可以使用 director 来准备多个服务器:

backend example1 {
  .host = "...";
  .port = "...";
  ...
}

为传入请求设置正确的后端(在 Varnish 中为:req)。我设置了一个附加值 req.http.backend,以便在后面的步骤中使用它。在这里,您可以替换或取消设置客户端请求的任何 HTTP 标头:

sub vcl_recv {
  ...
  if (req.http.host == "example1.mysite.com") {
    set req.backend = example1;
    set req.http.backend = "example1";
    set req.http.host = "application1.internal.mysite.com";
    unset req.http.Cache-Control;
    ...
  }
  ...
}

对返回的后端响应进行一些修改(在 Varnish 中:beresp)。如果您的应用程序有不同的主机名,您可能需要更改重定向。通常我会在这里删除一些 X-header 或替换后端的缓存标头:

sub vcl_fetch {
  ...
  if (req.http.backend == "example1") {
    ...
    unset beresp.http.X-Powered-By;
    ...
    if ((beresp.status == 301 || beresp.status == 302) && beresp.http.Location ~ "^http://application1\.internal\.mysite\.com") {
      set beresp.http.Location = regsub(beresp.http.Location, "^http://[^/]+", "http://example1.mysite.com");
    }
  }
  ...
}

示例 B)不同的 URL

在 Varnish 中,区别在于方法 vcl_recv。请注意您的应用程序能够使用路径名“/example1”。其他解决方案也是可能的,但我不推荐这样做:

sub vcl_recv {
  ...
  if (req.http.host == "www.mysite.com") {
    if (req.url ~ "(?i)^/example1/") {
      set req.backend = example1;
      set req.http.backend = "example1";
      set req.http.host = "application1.internal.mysite.com";
      unset req.http.Cache-Control;
      ...
    }
    ...
  }
  ...
}

您可以实现 A 或 B,也可以将 A 和 B 结合起来。(或多或少)使用 Varnish 一切皆有可能。

相关内容