为什么 Varnish 获取速度比绕过 Varnish 慢得多?
Why is Varnish fetch significantly slower than bypassing Varnish?
我已将 Varnish(端口 80)设置为缓存来自 Node.js 服务器(端口 8080)的请求,该服务器通常在个位数毫秒内响应(但有时会长得多)。
我在 PHP 中设置了一个简单的基准(我知道一次只会发送一个请求):
// Measure time for backend (bypassing Varnish by using port 8080)
$t = microtime(true);
foreach ($requests as $request){
file_get_contents($request["url"] . ":8080/?" . http_build_query($request["parameters"]));
}
$t = microtime(true) - $t;
echo "Backend: " . $t . "\n";
// Measure time for Varnish (using port 80 after Varnish restart)
$t = microtime(true);
foreach ($requests as $request){
file_get_contents($request["url"] . ":80/?" . http_build_query($request["parameters"]));
}
$t = microtime(true) - $t;
echo "Varnish MISS: " . $t . "\n";
// Measure time for Varnish (now cached)
$t = microtime(true);
foreach ($requests as $request){
file_get_contents($request["url"] . ":80/?" . http_build_query($request["parameters"]));
}
$t = microtime(true) - $t;
echo "Varnish HIT: " . $t . "\n";
// Results:
Backend: ~10 seconds
Varnish MISS: ~65 seconds
Varnish HIT: ~2 seconds
我测试了大约 1400 个请求。平均而言,Varnish 会为每个错过的请求增加 30-40 毫秒的开销。
Varnish 中缓存未命中的开销似乎大得惊人,我发现其他人也报告了类似的结果 - 然而,没有人能够解释为什么或如何减少开销。
所以我的问题是,为什么会有这么大的开销,我该如何减少它?
我知道缓存的想法是避免优化初始请求的响应时间,但是这个特定的网络服务会在短时间内看到大量的独特请求(但很多重新- 几天的请求),因此 Varnish 的开销有点重要。
清漆设置
vcl 4.0;
# Default backend definition. Set this to point to your content server.
backend default {
.host = "127.0.0.1";
.port = "8080";
}
sub vcl_recv {
unset req.http.Cookie;
}
sub vcl_backend_response {
}
sub vcl_deliver {
if (obj.hits > 0) {
set resp.http.X-Cache = "HIT";
} else {
set resp.http.X-Cache = "MISS";
}
}
在向 Varnish 人员询问了这个问题后,他们建议我尝试在同一台服务器但不同的后端上复制它。尝试使用 Apache 后端没有问题。
仔细检查来自 Varnish 的响应,我注意到对于 Node.js 服务器,在快速完成但没有完成的请求上会有 Content-Length header(由 Varnish 设置)关于那些完成缓慢的。
将 Content-Length header 添加到 Node.js 服务器响应(在 Apache 中默认添加)解决了这个问题。
我已将 Varnish(端口 80)设置为缓存来自 Node.js 服务器(端口 8080)的请求,该服务器通常在个位数毫秒内响应(但有时会长得多)。
我在 PHP 中设置了一个简单的基准(我知道一次只会发送一个请求):
// Measure time for backend (bypassing Varnish by using port 8080)
$t = microtime(true);
foreach ($requests as $request){
file_get_contents($request["url"] . ":8080/?" . http_build_query($request["parameters"]));
}
$t = microtime(true) - $t;
echo "Backend: " . $t . "\n";
// Measure time for Varnish (using port 80 after Varnish restart)
$t = microtime(true);
foreach ($requests as $request){
file_get_contents($request["url"] . ":80/?" . http_build_query($request["parameters"]));
}
$t = microtime(true) - $t;
echo "Varnish MISS: " . $t . "\n";
// Measure time for Varnish (now cached)
$t = microtime(true);
foreach ($requests as $request){
file_get_contents($request["url"] . ":80/?" . http_build_query($request["parameters"]));
}
$t = microtime(true) - $t;
echo "Varnish HIT: " . $t . "\n";
// Results:
Backend: ~10 seconds
Varnish MISS: ~65 seconds
Varnish HIT: ~2 seconds
我测试了大约 1400 个请求。平均而言,Varnish 会为每个错过的请求增加 30-40 毫秒的开销。
Varnish 中缓存未命中的开销似乎大得惊人,我发现其他人也报告了类似的结果 - 然而,没有人能够解释为什么或如何减少开销。
所以我的问题是,为什么会有这么大的开销,我该如何减少它?
我知道缓存的想法是避免优化初始请求的响应时间,但是这个特定的网络服务会在短时间内看到大量的独特请求(但很多重新- 几天的请求),因此 Varnish 的开销有点重要。
清漆设置
vcl 4.0;
# Default backend definition. Set this to point to your content server.
backend default {
.host = "127.0.0.1";
.port = "8080";
}
sub vcl_recv {
unset req.http.Cookie;
}
sub vcl_backend_response {
}
sub vcl_deliver {
if (obj.hits > 0) {
set resp.http.X-Cache = "HIT";
} else {
set resp.http.X-Cache = "MISS";
}
}
在向 Varnish 人员询问了这个问题后,他们建议我尝试在同一台服务器但不同的后端上复制它。尝试使用 Apache 后端没有问题。
仔细检查来自 Varnish 的响应,我注意到对于 Node.js 服务器,在快速完成但没有完成的请求上会有 Content-Length header(由 Varnish 设置)关于那些完成缓慢的。
将 Content-Length header 添加到 Node.js 服务器响应(在 Apache 中默认添加)解决了这个问题。