moy2010 Posted May 4, 2016 Share Posted May 4, 2016 (edited) Hi, Prestashop Community Members. I've been recently playing with Varnish 4 as an attempt to reduce my Prestashop 1.6 site's loading time. So far so good, the loading time have now decreased to ~1.5s and decided to share my VCL with the community so that we can create a big-single VCL configuration file for Varnish 4 for performance, security and a high hit-rate with the feedback from the whole community. Varnish 4 VCL for Prestashop v0.2 (Updated on May 06th, 2016): # # This is an example VCL file for Varnish. # # It does not do anything by default, delegating control to the # builtin VCL. The builtin VCL is called when there is no explicit # return statement. # # See the VCL chapters in the Users Guide at https://www.varnish-cache.org/docs/ # and http://varnish-cache.org/trac/wiki/VCLExamples for more examples. # Marker to tell the VCL compiler that this VCL has been adapted to the # new 4.0 format. 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 { # Only deal with "normal" types if (req.method != "GET" && req.method != "HEAD" && req.method != "PUT" && req.method != "POST" && req.method != "TRACE" && req.method != "OPTIONS" && req.method != "PATCH" && req.method != "DELETE") { /* Non-RFC2616 or CONNECT which is weird. */ return (pass); } # Only cache GET or HEAD requests. This makes sure the POST requests are always passed. if (req.method != "GET" && req.method != "HEAD") { return (pass); } # Some generic URL manipulation, useful for all templates that follow # First remove the Google Analytics added parameters, useless for our backend if (req.url ~ "(\?|&)(utm_source|utm_medium|utm_campaign|utm_content|gclid|cx|ie|cof|siteurl)=") { set req.url = regsuball(req.url, "&(utm_source|utm_medium|utm_campaign|utm_content|gclid|cx|ie|cof|siteurl)=([A-z0-9_\-\.%25]+)", ""); set req.url = regsuball(req.url, "\?(utm_source|utm_medium|utm_campaign|utm_content|gclid|cx|ie|cof|siteurl)=([A-z0-9_\-\.%25]+)", "?"); set req.url = regsub(req.url, "\?$", ""); } # Strip a trailing ? if it exists if (req.url ~ "\?$") { set req.url = regsub(req.url, "\?$", ""); } # Strip hash, server doesn't need it. if (req.url ~ "\#") { set req.url = regsub(req.url, "\#.*$", ""); } if (req.http.Accept-Encoding) { # Do no compress compressed files... if (req.url ~ "\.(jpg|png|gif|woff2|gz|tgz|bz2|tbz)$") { unset 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 { unset req.http.Accept-Encoding; } } # Remove the "has_js" cookie set req.http.Cookie = regsuball(req.http.Cookie, "has_js=[^;]+(; )?", ""); # Remove any Google Analytics based cookies set req.http.Cookie = regsuball(req.http.Cookie, "__utm.=[^;]+(; )?", ""); set req.http.Cookie = regsuball(req.http.Cookie, "_ga=[^;]+(; )?", ""); set req.http.Cookie = regsuball(req.http.Cookie, "_gat=[^;]+(; )?", ""); set req.http.Cookie = regsuball(req.http.Cookie, "utmctr=[^;]+(; )?", ""); set req.http.Cookie = regsuball(req.http.Cookie, "utmcmd.=[^;]+(; )?", ""); set req.http.Cookie = regsuball(req.http.Cookie, "utmccn.=[^;]+(; )?", ""); # Remove DoubleClick offensive cookies set req.http.Cookie = regsuball(req.http.Cookie, "__gads=[^;]+(; )?", ""); # Remove the Quant Capital cookies (added by some plugin, all __qca) set req.http.Cookie = regsuball(req.http.Cookie, "__qc.=[^;]+(; )?", ""); # Remove the AddThis cookies set req.http.Cookie = regsuball(req.http.Cookie, "__atuv.=[^;]+(; )?", ""); # Remove a ";" prefix in the cookie if present set req.http.Cookie = regsuball(req.http.Cookie, "^;\s*", ""); # Are there cookies left with only spaces or that are empty? if (req.http.cookie ~ "^\s*$") { unset req.http.cookie; } #we should not cache any page for sales if (req.method == "GET" && (req.url ~ "^/cart.php" || req.url ~ "^/order.php")) { return (pass); } #we should not cache any page for sales if (req.method == "GET" && (req.url ~ "^/addresses.php" || req.url ~ "^/order-detail.php")) { return (pass); } #we should not cache any page for sales if (req.method == "GET" && (req.url ~ "^/order-confirmation.php" || req.url ~ "^/order-return.php")) { return (pass); } if (req.url ~ "^[^?]*\.(css|js|jpg|png|gif|woff|woff2)(\?.*)?$") { unset req.http.Cookie; } if (req.http.Authorization || req.http.Authenticate) { return (pass); } } sub vcl_backend_response { # Avoid Header Expires in the past if (beresp.ttl > 0s && (bereq.method == "GET" || bereq.method == "HEAD")) { unset beresp.http.set-cookie; unset beresp.http.Expires; set beresp.ttl = 24h; unset beresp.http.Cache-Control; # Set new Cache-Control headers for browsers to store cache for 7 days set beresp.http.Cache-Control = "public, max-age=604800"; set beresp.http.magicmarker = "1"; set beresp.http.cachable = "1"; if (bereq.url !~ "\.(css|js|jpg|png|gif|woff|woff2|html|htm|gz)(\?|$)") { set beresp.http.Pragma = "no-cache"; set beresp.http.Expires = "-1"; set beresp.http.Cache-Control = "no-store, no-cache, must-revalidate, max-age=0"; set beresp.grace = 1m; } return(deliver); } # Sometimes, a 301 or 302 redirect formed via Apache's mod_rewrite can mess with the HTTP port that is being passed along. # This often happens with simple rewrite rules in a scenario where Varnish runs on :80 and Apache on :8080 on the same box. # A redirect can then often redirect the end-user to a URL on :8080, where it should be :80. # This may need finetuning on your setup. # # To prevent accidental replace, we only filter the 301/302 redirects for now. if (beresp.status == 301 || beresp.status == 302) { set beresp.http.Location = regsub(beresp.http.Location, ":[0-9]+", ""); } # Don't cache 50x responses if (beresp.status == 500 || beresp.status == 502 || beresp.status == 503 || beresp.status == 504) { return (abandon); } # Allow stale content, in case the backend goes down. # make Varnish keep all objects for 1 hour beyond their TTL set beresp.grace = 1h; return (deliver); } sub vcl_deliver { if(obj.hits > 0) { set resp.http.X-Cache = "HIT"; } else { set resp.http.X-Cache = "MISS"; } # Remove some headers: PHP version unset resp.http.X-Powered-By; # Remove some headers: Apache version & OS unset resp.http.Server; # Remove some heanders: Varnish unset resp.http.Via; unset resp.http.X-Varnish; } Edited May 6, 2016 by moy2010 (see edit history) 5 Link to comment Share on other sites More sharing options...
tuk66 Posted May 5, 2016 Share Posted May 5, 2016 Thanks for sharing. Link to comment Share on other sites More sharing options...
moy2010 Posted May 6, 2016 Author Share Posted May 6, 2016 Varnish 4 VCL Update Changes:- Normalize the accept-encoding headers - Prevent an object having a exprie date in the past - Some additional tuning Link to comment Share on other sites More sharing options...
zanpo Posted May 15, 2016 Share Posted May 15, 2016 Thanks for sharing! I am using it on my server, but I am only getting MISS-es, I don't know why, can you help please? Accept-Ranges:bytes Age:0 Connection:keep-alive Content-Encoding:gzip Content-Type:text/html; charset=utf-8 Date:Sun, 15 May 2016 22:51:01 GMT P3P:CP="IDC DSP COR CURa ADMa OUR IND PHY ONL COM STA" Server:nginx Transfer-Encoding:chunked Vary:Accept-Encoding Via:1.1 varnish-v4 X-Cache:MISS X-Varnish:262170 Link to comment Share on other sites More sharing options...
moy2010 Posted May 17, 2016 Author Share Posted May 17, 2016 Check if you are performing the tests while logged in. Varnish doesn't handle cookies, and the VCL I shared completely misses the varnish cache for logged users. Link to comment Share on other sites More sharing options...
Dh42 Posted May 17, 2016 Share Posted May 17, 2016 Does your layered navigation work with that file? It strips hashes. Link to comment Share on other sites More sharing options...
moy2010 Posted May 17, 2016 Author Share Posted May 17, 2016 Does your layered navigation work with that file? It strips hashes. I'm not using it, I use Advanced Search 4 instead and everything works fine . Link to comment Share on other sites More sharing options...
zanpo Posted May 22, 2016 Share Posted May 22, 2016 Check if you are performing the tests while logged in. Varnish doesn't handle cookies, and the VCL I shared completely misses the varnish cache for logged users. I am not logged in, not in front, not in admin. I tried browsing in "incognito" mode and still only MISS. Cleared all the history in the browser and only MISS. Link to comment Share on other sites More sharing options...
moy2010 Posted May 22, 2016 Author Share Posted May 22, 2016 I am not logged in, not in front, not in admin. I tried browsing in "incognito" mode and still only MISS. Cleared all the history in the browser and only MISS. Then check the url of a static content such as an image with this website: http://www.isvarnishworking.com/ Also check that your expires or cache-control headers are properly set. 1 Link to comment Share on other sites More sharing options...
oxoCreations Posted June 19, 2016 Share Posted June 19, 2016 Hello, thanks for sharing you VCL ! I've a problem between varnish and Google pagespeed tool. With your configuration I can access to my website. Any idea ? For more speed on Prestashop, it would be interested to focus on 3 points : varnish, pagespeed and htaccess ! thx for answer Link to comment Share on other sites More sharing options...
moy2010 Posted June 21, 2016 Author Share Posted June 21, 2016 Right now Varnish isn't compatible with mod_pagespeed. You have to use plain apache/nginx or a mix of these as your server's backend. Link to comment Share on other sites More sharing options...
flo62134 Posted September 12, 2016 Share Posted September 12, 2016 (edited) Thank you very much for sharing this configuration, it works like a charm !However, with this configuration, the very first request is always a miss, is it normal ?For example, when I try to load the home page, the "/" request is always a miss and the very first request of a category page or a CMS page is always a miss.Although, all the other resources are fine and properly cached. I think it is due to the presence of the HTML code containing the cart and the amount of the cart, am I right ? Thank you very much for your help Edited September 12, 2016 by flo62134 (see edit history) Link to comment Share on other sites More sharing options...
moy2010 Posted September 18, 2016 Author Share Posted September 18, 2016 Hi, flo62134. Indeed there are multiple explanations for a miss with varnish cache as you said. Varnish cache works with objects and it's based on urls, so that if you call the same object from multiple urls you will have duplicated objects in your cache. In my case, I had to normalize all my urls prior to achieving a high hitrate in varnish. A common example is to redirect all www.yoursite.com traffic to yoursite.com or the other way around. If your varnish sits behind your web server, you'll have to make the redirections on varnish, otherwise it may always have a miss on the first request. In conclusion:Check the first request in terms of objects and urls. If you find what's different between the requested and the cached object you'll find what the problem is. Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now