Reputation: 2391
I've set up Varnish (port 80) to cache requests from a Node.js server (port 8080) that usually responds in single-digit miliseconds (but some times significantly longer).
I set up a simple benchmark in PHP (I'm aware that'll only send one request at a time):
// 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
I test with ~1400 requests. On average Varnish adds 30-40 miliseconds of overhead to each request that is missed.
The overhead from a cache miss in Varnish seems obscenely large and I've found others reporting similar results - no one able to explain why or how to reduce the overhead, however.
So my question is, why is there such a large overhead and how can I reduce it?
I know that the idea of caching is to avoid optimizing the response time of the initial request, but this particular web service will see a large amount of unique requests in a short time (but many re-requests over a couple of days), so the overhead from Varnish is somewhat important.
Varnish setup
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";
}
}
Upvotes: 1
Views: 810
Reputation: 2391
After asking the Varnish guys about the issue, they suggested I try and replicate it on the same server but different backend. Trying that with an Apache backend there were no issues.
Examining the responses from Varnish closer I noticed that with the Node.js server there would be a Content-Length header (set by Varnish) on the requests that finished quickly, but not on those that finished slowly.
Adding a Content-Length header to the Node.js server response (which is added by default in Apache) fixed the issue.
Upvotes: 2