Madison PHP Conference
September 13th, 2014
© David Buchmann, Liip AG
apt-get install varnish
/etc/default/varnish, replace port 6081 by port 80
service 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 })) %}