我正在尝试使用 Varnish 4.1 实现 rubygems 反向代理。我的 Intranet 内的客户端没有通用的出站 NAT,因此我需要 Varnish 在内部跟踪所有重定向,最好缓存来自 rubygems.org 的 302 和来自 CDN 服务器的响应。
这是我的默认.vcl:
vcl 4.0;
import std;
backend default {
.host = "rubygems.org";
.port = "80";
}
sub vcl_recv {
std.syslog(180, "doing vcl_recv");
std.syslog(180, "req.url = " + req.url);
}
sub vcl_deliver {
std.syslog(180, "doing vcl_deliver");
std.syslog(180, "resp.status = " + resp.status);
if (resp.status == 302) {
set req.url = resp.http.Location;
std.syslog(180, "restarting with req.url = " + req.url);
return(restart);
}
}
sub vcl_backend_fetch {
std.syslog(180, "doing vcl_backend_fetch");
std.syslog(180, "bereq.retries = " + bereq.retries);
}
sub vcl_backend_error {
std.syslog(180, "doing vcl_backend_error");
}
如果我curl -i http://localhost/latest_specs.4.8.gz
,Varnish 会抛出 HTTP 503 并记录以下内容:
varnishd[20384]: doing vcl_recv
varnishd[20384]: req.url = /latest_specs.4.8.gz
varnishd[20384]: doing vcl_backend_fetch
varnishd[20384]: bereq.retries = 0
varnishd[20384]: doing vcl_deliver
varnishd[20384]: resp.status = 302
varnishd[20384]: restarting with req.url = http://rubygems.global.ssl.fastly.net/latest_specs.4.8.gz
varnishd[20384]: doing vcl_recv
varnishd[20384]: req.url = http://rubygems.global.ssl.fastly.net/latest_specs.4.8.gz
varnishd[20384]: doing vcl_backend_fetch
varnishd[20384]: bereq.retries = 0
varnishd[20384]: doing vcl_deliver
varnishd[20384]: resp.status = 302
varnishd[20384]: restarting with req.url = http://rubygems.global.ssl.fastly.net/latest_specs.4.8.gz
varnishd[20384]: doing vcl_recv
varnishd[20384]: req.url = http://rubygems.global.ssl.fastly.net/latest_specs.4.8.gz
varnishd[20384]: doing vcl_backend_fetch
varnishd[20384]: bereq.retries = 0
varnishd[20384]: doing vcl_deliver
varnishd[20384]: resp.status = 302
varnishd[20384]: restarting with req.url = http://rubygems.global.ssl.fastly.net/latest_specs.4.8.gz
varnishd[20384]: doing vcl_recv
varnishd[20384]: req.url = http://rubygems.global.ssl.fastly.net/latest_specs.4.8.gz
varnishd[20384]: doing vcl_backend_fetch
varnishd[20384]: bereq.retries = 0
varnishd[20384]: doing vcl_deliver
varnishd[20384]: resp.status = 302
varnishd[20384]: restarting with req.url = http://rubygems.global.ssl.fastly.net/latest_specs.4.8.gz
即使在更新 req.url 并重新启动请求后,它似乎也没有请求新 URL。
这不是一个明确的答案,但这里有一些想法:
1) "req.url"仅包含URL的路径部分,但不包含URL的协议和主机部分。因此,当您在vcl_deliver中将"http://rubygems.global.ssl.fastly.net/latest_specs.4.8.gz"分配给"req.url"然后重新启动时,这对我来说似乎是完全错误的。
在我看来,重新启动的请求不会命中"rubygems.global.ssl.fastly.net",但仍然会命中"rubygems.org"——定义的默认后端。
所以我想你需要定义第二个后端"rubygems.global.ssl.fastly.net"并在重新启动时进行设置。您还需要执行类似操作(未经测试)
set resp.http.Location = regsub(resp.http.Location,"^http://","");
set req.http.host = regsub(resp.http.Location,"/.*$","");
set req.url = regsub(resp.http.Location,"[^/]*","");
2) 重试和重新启动是清漆 4 中的不同概念
这就是为什么bereq.retry总是显示0。您需要查看 req.restarts