Madison PHP Conference
September 13th, 2014
© David Buchmann, Liip AG
apt-get install varnish
/etc/default/varnish
, replace port 6081 by port 80service apache2 restart service varnish restart
GET /path HTTP/1.1 200 OK Content-Type: text/html <html>...</html>
https://twitter.com/stevelosh/status/372740571749572610
http://httpstatusdogs.com
Cache-Control: s-maxage=3600, max-age=900 Expires: Thu, 15 May 2014 08:00:00 GMT
Cache-Control: s-maxage=0, private, no-cache
Accept: application/json
Vary: Accept
ETag: 82901821233
If-None-Match: 82901821233 304 Not Modified
Last-Modified: Tue, 13 May 2014 08:13:20 GMT
If-Modified-Since: Tue, 13 May 2014 08:13:20 GMT 304 Not Modified
wget -Sq --spider http://localhost/path.html curl -o /dev/null -sD - http://cmf.lo/app_dev.php
// setting headers is no longer possible // when output started! header('Cache-Control: s-maxage=600, max-age=60'); header('Etag: ' . sha1($data));
// DefaultController::indexAction $response = $this->render('::index.html.twig'); $response->setSharedMaxAge(600); $response->setMaxAge(60); $response->setEtag(sha1($response->getContent())); return $response;
# ... # Cache the homepage for 10 minutes - match: path: ^/$ headers: cache_control: public: true max_age: 600
vcl_recv: entry point, lookup or pass vcl_fetch: receive from backend, cache or not vcl_deliver: remove headers not for client vcl_hash: determine cache key vcl_hit: found in cache, deliver or pass vcl_miss: pass or fetch vcl_pipe: do not alter request vcl_error: define error page
Think carefully and test thoroughly
sub vcl_deliver { if (obj.hits > 0) { set resp.http.X-Cache = "HIT"; } else { set resp.http.X-Cache = "MISS"; } }
sub vcl_recv { if (req.http.Cookie) { if (req.url ~ "^/static") { remove req.http.Cookie; } } }
sub vcl_recv { if (req.http.Cookie) { # removes all cookies named __utm? (utma, ...) set req.http.Cookie = regsuball( req.http.Cookie, "(^|; ) *__utm.=[^;]+;? *", "\1" ); if (req.http.Cookie == "") { remove req.http.Cookie; } }
<link rel="stylesheet" href="/css/style.css?v1" type="text/css"/> ... <script src="/js/scripts.js?v1"></script>
Built-in support for cache busting with Symfony & Assetic:
# app/config.yml framework: templating: assets_version: v1
acl invalidators { "localhost"; } sub vcl_recv { if (req.request == "PURGE") { if (!client.ip ~ invalidators) { error 405 "PURGE not allowed"; } return (lookup); } } ...
... sub vcl_hit { if (req.request == "PURGE") { purge; error 200 "Purged"; } } sub vcl_miss { if (req.request == "PURGE") { purge; error 200 "Purged (not found)"; } }
$cacheInvalidator->invalidatePath('/my/path'); ... $cacheInvalidator->flush();
// CommentsController::postAction // page changed, send purge request for this url ... $cacheManager = $container->get( 'fos_http_cache.cache_manager' ); $cacheManager->invalidateRoute('page', array( 'id' => $post->getPage()->getId() ); ...
# app/config.yml fos_http_cache: proxy_client: varnish: servers: 4.4.4.11:80, 4.4.4.22:80 base_url: yourwebsite.com
Group based caching
X-Cache-Tags: comment1, comment2
ban("obj.http.x-cache-tags ~ " + req.http.x-cache-tags );
/** @var $cm CacheManageer */ $cm->tagResponse($response, array('comment-42')); ... $cm->invalidateTags(array('comment-42'));
use FOS\HttpCacheBundle\Configuration\Tag; class CommentController extends Controller { /** * @Tag({"comments", "'comment-'~id"}) */ public function commentAction($id) { // ...
<html> <body> Main body. <esi:include src="/esi-fragment.php" /> </body> </html>
-p esi_syntax=0x00000003
sub vcl_recv { // Announce ESI support to backend. set req.http.Surrogate-Capability = "abc=ESI/1.0"; } sub vcl_fetch { // Check for ESI acknowledgement if (beresp.http.Surrogate-Control ~ "ESI/1.0") { unset beresp.http.Surrogate-Control; set beresp.do_esi = true; } }
# app/config/config.yml framework: esi: { enabled: true } fragments: { path: /_fragment }Make sure either your webserver is only reachable from the Varnish server or add access restrictions for /_fragment
{# index.html.twig #} {% render_esi(controller( 'DbuCoreBundle:Comments:comments', {'param': 42 })) %}