我正在尝试使用 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 一切皆有可能。