Any one know why we are getting a very low cache hit rate average when using Wordpress (With Varnish and Nginx)?
Varnish stat shows :
Hitrate ratio: 10 100 518 Hitrate avg: 0.4143 0.2690 0.1948
Any idea how to fix this? My varnish default.vcl is :
# This is a basic VCL configuration file for varnish. See the vcl(7)
# man page for details on VCL syntax and semantics.
#
# Default backend definition. Set this to point to your content
# server.
#
backend default {
.host = "77.81.240.177";
.port = "8080";
}
acl purge {
"77.81.240.177";
}
sub vcl_recv {
# Add a unique header containing the client address
remove req.http.X-Forwarded-For;
#set req.http.X-Forwarded-For = client.ip;
set req.http.X-Forwarded-For = req.http.rlnclientipaddr;
# Let's make sure we aren't compressing already compressed formats.
if (req.http.Accept-Encoding) {
if (req.url ~ "\.(jpg|png|gif|gz|tgz|bz2|mp3|mp4|m4v)(\?.*|)$") {
remove req.http.Accept-Encoding;
} elsif (req.http.Accept-Encoding ~ "gzip") {
set req.http.Accept-Encoding = "gzip";
} elsif (req.http.Accept-Encoding ~ "deflate") {
set req.http.Accept-Encoding = "deflate";
} else {
remove req.http.Accept-Encoding;
}
}
if (req.request == "PURGE") {
if (!client.ip ~ purge) {
error 405 "Not allowed.";
}
return(lookup);
}
if (req.url ~ "^/$") {
unset req.http.cookie;
}
}
sub vcl_hit {
if (req.request == "PURGE") {
set obj.ttl = 0s;
error 200 "Purged.";
}
}
sub vcl_miss {
if (req.request == "PURGE") {
error 404 "Not in cache.";
}
if (!(req.url ~ "wp-(login|admin)")) {
unset req.http.cookie;
}
if (req.url ~ "^/[^?]+.(jpeg|jpg|png|gif|ico|js|css|txt|gz|zip|lzma|bz2|tgz|tbz|html|htm)(\?.|)$") {
unset req.http.cookie;
set req.url = regsub(req.url, "\?.$", "");
}
if (req.url ~ "^/$") {
unset req.http.cookie;
}
}
sub vcl_fetch {
if (req.url ~ "^/$") {
unset beresp.http.set-cookie;
}
if (!(req.url ~ "wp-(login|admin)")) {
unset beresp.http.set-cookie;
}
if (req.url ~ "^/w00tw00t") {
error 403 "Not permitted";
}
}
A good approach is to inspect the traffic with varnishlog in order to see what makes which rules apply.
Since you're not enforcing a TTL, my guess is that the wordpress site delivers Cache-Control headers like "max-age: 0", or "no-cache" "private" or something, and varnish honors such headers unless you specifically tell it not to, i.e:
First rule in vcl_fetch does not make sense, as second rule will unset all set-cookies for all urls but wp-login/wp-admin.
Add some config to vcl_deliver to output headers that states if it's a hit or not:
Other feedback to you config:
In vcl_recv, you do "unset req.http.cookie" if url is not wp-login or wp-admin, which means that if a user logs on /wp-login then goes to "/", you will unset his cookie. You only need to unset cookies in vcl_recv for urls that shouldn't ever need one, ie .(js|css|png|jpg) etc, and instead remove the set-cookie in vcl_fetch.
wp-varnish
Checkout wp-varnish - A plugin for WordPress that will purge content in Varnish when content in WordPress is changed. It also comes with a sample VCL which should give you a better hitrate
Sample VCL