Joel Wurtz / @joelwurtz
Un cache réduit le coût des ressources.
Un cache transforme le coût des ressources.
On réduit le calcul mais on augmente le stockage.
Response
Request
Support de la norme HTTP
$response->setPublic();
$response->setPrivate();
$response->setMaxAge(600);
$response->setSharedMaxAge(600);
$response->setExpires(new \DateTime());
$response->setLastModified(new \DateTime());
// Ou
$response->setETag("1121029380192");
if ($response->isNotModified($request)) {
return $response;
}
$response->setVary('User-Agent');
$kernel = new AppCache($kernel);
Suffisant, mais pas très performant (~20-40ms).
La bonne nouvelle est qu'il est très simple de passer d'un proxy à un autre sans qu'aucune modification ne soit nécessaire dans le code.
apt-get update
apt-get install varnish
Norme HTTP ?
Au lieu d'attendre le nouveau cache on peut envoyer l'ancien (stale response)
Garder la réponse pendant 10 minutes après qu'elle soit invalide.
sub vcl_fetch {
set beresp.grace = 10m;
}
On peut utiliser l'ancien cache pour cette requête pendant 10 min
sub vcl_recv {
set req.grace = 10m;
}
Objectif: servir du cache si on obtient une erreur 500
sub vcl_fetch {
if (beresp.status == 500) {
set beresp.saintmode = 30s;
return(restart);
}
set beresp.grace = 5m;
}
Cookie = pas de cache
sub vcl_recv {
...
return (lookup);
}
sub vcl_recv {
set req.http.X-TempCookie = req.http.cookie;
unset req.http.cookie;
}
sub vcl_miss {
if (bereq.http.X-TempCookie) {
set bereq.http.cookie = bereq.http.X-TempCookie;
}
}
sub vcl_pass {
if (bereq.http.X-TempCookie) {
set bereq.http.cookie = bereq.http.X-TempCookie;
}
}
Les personnes connectées / non-connectées auront le même cache.
Marche uniquement si on force un `return (lookup);`
$response->setVary('Cookie');
Google analytics ? Cache différent pour chaque appel.
sub vcl_recv {
set req.http.X-Session-Id = ";" + req.http.cookie;
set req.http.X-Session-Id = regsuball(req.http.X-Session-Id, "; +", ";");
set req.http.X-Session-Id = regsuball(req.http.X-Session-Id, ";(PHPSESSID)=", "; \1=");
set req.http.X-Session-Id = regsuball(req.http.X-Session-Id, ";[^ ][^;]*", "");
set req.http.X-Session-Id = regsuball(req.http.X-Session-Id, "^[; ]+|[; ]+$", "");
}
$reponse->setVary('X-SessionId')
Un cache par utilisateur, niveau performance on a vu mieux.
Problèmes :
Voir documentation FOSHttpCache
sub vcl_recv {
// Handle the original request: send a HEAD request to retrieve the user hash
if (req.restarts == 0 && req.http.cookie && (req.request == "GET" || req.request == "HEAD")) {
set req.http.x-original-url = req.url;
set req.http.x-original-request = req.request;
# Retrieve a unique session id from the cookie
set req.http.x-session-id = req.http.cookie;
set req.url = "/generate_hash.php";
set req.request = "HEAD";
return (lookup);
}
// After the HEAD request, reset the request to the original one, which
// will be restarted in vcl_deliver.
if (req.restarts > 0 && req.http.X-Original-Method) {
set req.request = req.http.x-original-method;
set req.url = req.http.x-original-url;
unset req.http.req.http.x-original-method;
unset req.http.req.http.x-original-url;
return (lookup);
}
}
sub vcl_miss {
// When creating backend request, varnish force GET method (bug ?)
set bereq.request = req.request;
}
sub vcl_deliver {
// After receiving the HEAD response, copy the hash to the original request
// and restart that.
if (req.request == "HEAD" && resp.http.x-user-context-hash) {
set req.http.x-user-context-hash = resp.http.x-user-context-hash;
return (restart);
}
}
Slides sur http://jolicode.github.io/http-cache-conf/