Upload
sqli
View
555
Download
0
Embed Size (px)
Citation preview
Digital performance.
VARNISH
MEET-UP
Cédric Bezaud - 22/09/2015
+Présentation
+Concrètement … Ca donne quoi ?
+Concrètement … Comment ca marche ?
+Concrètement … Ca ressemble a quoi ?
+Les Plus / Les Moins
+Conclusion / Questions
VARNISH SOMMAIRE
© SQLI Enterprise – SQLI GROUP | 2015 2
PRÉSENTATION
+Varnish est un serveur de cache HTTP en ReverseProxy
+Il est apparut en 2006.
+Il est distribué sous licence BSD
+Il est utilisé par de très grands sites comme Facebook, Pinterest,
LeMonde, linternaute, JournalDuNet...
+La version actuelle est la version 4 (Avril 2014)
+Il est écrit en Language C
VARNISH PRÉSENTATION
© SQLI Enterprise – SQLI GROUP | 2015 4
+Il se configure via le language VCL (Varnish Configuration Language)
+Il est extensible via des VMODs (Varnish Modules) (ex : Variable
Support, JSON, Rewrite, Redirect…)
+Il fonctionne sur un environnement Linux
(Red Hat, Debian, Ubuntu, FreeBSD …)
+Il peux également fonctionner sous Mac OS et Windows (via Cygwin)
VARNISH PRÉSENTATION
© SQLI Enterprise – SQLI GROUP | 2015 5
VARNISH OU LE MET ON ?
© SQLI Enterprise – SQLI GROUP | 2015 6
Navigateur Utilisateurs Serveur applicatif Serveur de cache
en ReverseProxy
EN CHIFFRE CA DONNE QUOI ?
+ Test N°1 : Site sur un site Drupal 7 › Apache 2
› PHP 5.5
› MySQL 5.5
› 110 000 requêtes…
+ Test N°2 : Site du même site Drupal 7 › Varnish 3
› Apache 2
› PHP 5.5
› MySQL 5.5
› Les mêmes 110 000 requêtes…
EN CHIFFRE CA FAIT QUOI ?
© SQLI Enterprise – SQLI GROUP | 2015 8
PETIT TEST VIA JMETER
COMMENT CA MARCHE ?
+ Cache « MISS »
VARNISH COMMENT CA MARCHE ( EN SIMPLE )
© SQLI Enterprise – SQLI GROUP | 2015 14
Recv Hash Miss Deliver
Recv Hash Hit
+ Cache « HIT »
Deliver
Fetch BackEnd
+ vcl_recv
› Normalise les requêtes en entrée
› Premiers filtres
› Sécurise
› Correction d’erreurs …
+ vcl_pipe
› Liaison non http (pipe)
+ vcl_hash
› Définition de la clé du cache (clé unique)
+ vcl_hit
› Cache « Hit »
VARNISH 3 COMMENT CA MARCHE
© SQLI Enterprise – SQLI GROUP | 2015 15
+ vcl_miss
› Cache « Miss »
+ vcl_pass
› ByPass : On force a aller chercher la réponse depuis le backend
+ vcl_fetch
› Règle de cache de l’objet backend
+ vcl_deliver
› Restitution de la réponse
+ vcl_error
› Affichage d’une page d’erreur
VARNISH 3 COMMENT CA MARCHE
© SQLI Enterprise – SQLI GROUP | 2015 16
+ vcl_recv
+ vcl_pipe
+ vcl_hash
+ waiting
› Gestion d’une file d’attente
+ vcl_hit
+ vcl_miss
+ vcl_purge
› Sub routine dédié à l’invalidation de cache
VARNISH 4 COMMENT CA MARCHE
© SQLI Enterprise – SQLI GROUP | 2015 17
+ vcl_fetch découpé par
› vcl_backend_fetch
› vcl_backend_response
› vcl_backend_error
+ vcl_deliver
+ vcl_error remplacé par vcl_synth
VARNISH 4 COMMENT CA MARCHE
© SQLI Enterprise – SQLI GROUP | 2015 18
AUTRE FONCTIONNALITÉS
+ ReverseProxy › Plusieurs backend derrière (homogène ou hétérogène)
+ LoadBalancing (via les directors) › RoundRobin (pondéré) › Client (permet de faire du sticky session sur n’importe quel élément du header) › Random › Hash mode (Version 4)
+ Compression HTTP (depuis Varnish 3) › Économiser de la bande passante entre Varnish et le Client (navigateurs, applications, etc …). › Économiser de la place dans le cache de Varnish (et donc de la mémoire RAM). › Économiser de la bande passante entre le backend et Varnish (peu pertinent, souvent le même VLAN). › Économiser le CPU du backend lors de la compression
+ ESI (Egde Side Includes) (req.esi en détection, beresp.do_esi = true pour relayer au backend ) › Cache partiel …
+ Réécriture d’URL (réécriture simple, pour des réécriture plus complexe, il faut passer par un VMOD)
+ ACL (Access Control List)
VARNISH AUTRES FONCTIONNALITÉS
© SQLI Enterprise – SQLI GROUP | 2015 20
CA RESSEMBLE A QUOI ?
VARNISH
© SQLI Enterprise – SQLI GROUP | 2015 22
# Définition du subnet Internal et purge, pour la gestion des ACLs (abordé plus bas) acl internal { "localhost" "192.10.0.0"/24; } acl purge { "localhost" } # # Default backend definition. # Création du backend « default » répondant à l’adresse 127.0.0.1 port 8080
#
backend default {
.host = "127.0.0.1";
.port = "8080";
}
VARNISH
© SQLI Enterprise – SQLI GROUP | 2015 23
# Répond au requête entrante sub vcl_recv {
if (req.request == "GET" && req.url ~ "^/varnishcheck$" && client.ip ~ internal) { error 200 "Varnish is Ready"; } # Si le backend ne réponds plus, suppression de tous les cookies (=> connexion anonyme).
if (!req.backend.healthy) {
unset req.http.Cookie; if (req.http.X-Forwarded-Proto == "https") { set req.http.X-Forwarded-Proto = "http"; } set req.grace = 30m;
} else { set req.grace = 15s; }
# C’est du streaming => au pipe
if ( res.url ~ "^admin/content/backup_migrate/export" ) { return (pipe);
}
VARNISH
© SQLI Enterprise – SQLI GROUP | 2015 24
if (req.restarts == 0) {
if (req.http.x-forwarded-for) {
set req.http.X-Forwarded-For = req.http.X-Forwarded-For + ", " + client.ip;
}
else {
set req.http.X-Forwarded-For = client.ip;
}
}
# Pas de cache pour les urls ci-dessous (Regex)
if (req.url ~ "^/status\.php$" ||
req.url ~ "^/update\.php$" ||
req.url ~ "^/admin$" ||
req.url ~ "^/admin/.*$" ||
req.url ~ "^/flag/.*$" ||
req.url ~ "^.*/ajax/.*$" ||
req.url ~ "^.*/ahah/.*$") {
return (pass);
}
VARNISH
© SQLI Enterprise – SQLI GROUP | 2015 25
# Autorisation d’accès à cron.php ou install.php.
if (req.url ~ "^/(cron|install|update)\.php$" && !client.ip ~ internal) {
# Utilisation de la gestion d’erreur Varnish.
error 403 "Forbiden."; # remplacer par synth(403, "Forbiden.") # Utilisation d’une page d’erreur définie dans le Backend ("/404" ).
# set req.url = "/404";
} # Normalisation du header Accept-Encoding (http://varnish-cache.org/wiki/FAQ/Compression) if (req.http.Accept-Encoding) { if (req.url ~ "\.(jpg|png|gif|gz|tgz|bz2|tbz|mp3|ogg)$") { # Suppression de l’entête Accept-Encoding remove req.http.Accept-Encoding; } elsif (req.http.Accept-Encoding ~ "gzip") { set req.http.Accept-Encoding = "gzip"; } else { # Encodage inconnu suppression de l’entête Accept-Encoding remove req.http.Accept-Encoding; } }
VARNISH
© SQLI Enterprise – SQLI GROUP | 2015 26
# Toujours cacher les extensions ci-dessous (voir ci-dessous)
if (req.url ~ "(?i)\.(pdf|asc|dat|txt|…|gif|jpeg|jpg|ico|swf|css|js)(\?.*)?$") {
unset req.http.Cookie;
} # Exemple de netoyage de cookies. if (req.http.Cookie) {
# 1. Ajoute un « ; » devant la chaine de cookie.
set req.http.Cookie = ";" + req.http.Cookie;
# 2. Supprime les espaces juste après les « ; ». set req.http.Cookie = regsuball(req.http.Cookie, "; +", ";");
# 3. Match des cookies que l’on veux garder, ajout d’un espace devant… set req.http.Cookie = regsuball(req.http.Cookie, ";(SESS[a-z0-9]+|NO_CACHE)=", "; \1="); # 4. Suppression des autres cookies (ils n’ont pas d’espace après le « ; »). set req.http.Cookie = regsuball(req.http.Cookie, ";[^ ][^;]*", "");
# 5. Suppression des « ; » et des espaces non significatifs.
set req.http.Cookie = regsuball(req.http.Cookie, "^[; ]+|[; ]+$", ""); if (req.http.Cookie == "") { # Si le cookie est vide, on supprime l’entête
unset req.http.Cookie;
}
else { # Si il reste des cookies, on demande au backend
return (pass);
}
}
VARNISH
© SQLI Enterprise – SQLI GROUP | 2015 27
# Non conforme à la RFC-2616 – le verbe CONNECT, on autorise également le verbe PURGE if (req.request != "GET" && req.request != "HEAD" && req.request != "PUT" && req.request != "POST" && req.request != "TRACE" && req.request != "OPTIONS" && req.request != "PURGE" && req.request != "DELETE") { return (pipe); } # Si le verbe est différant de GET, HEAD, PURGE if (req.request != "GET" && req.request != "HEAD" && req.request != "PURGE" ) { return (pass); # PAS DE CACHE } # Si on nous demande une authentification HTTP ou qu’il reste un cookie (session ouverte) if (req.http.Authorization || req.http.Cookie) { return (pass); # PAS DE CACHE } }
VARNISH
© SQLI Enterprise – SQLI GROUP | 2015 28
# Détermination de la clé unique de stockage du cache
sub vcl_hash {
if (req.http.X-Forwarded-Proto == "https") { hash_data(req.http.X-Forwarded-Proto);
}
} # Cache Hit sub vcl_hit { if (req.request == "PURGE" && client.ip ~ purge) { purge; # Le mot clé n’existe plus en VCL4 error 200 "Purged."; } } # Cache Miss sub vcl_miss { if (req.request == "PURGE" && client.ip ~ purge) { purge; # Le mot clé n’existe plus en VCL4 error 200 "Purged."; } }
VARNISH
© SQLI Enterprise – SQLI GROUP | 2015 29
# Traitement du retour du backend (backendresponse) # N’existe plus en VCL4 # Remplacé par vcl_backend_fetch, vcl_backend_response et vcl_bacckend_error
sub vcl_fetch {
# On cache les réponse 404, 301 et 500 pendant 10 minutes.
if (beresp.status == 404 || beresp.status == 301 || beresp.status == 500) {
set beresp.ttl = 10m;
}
# Suppression des cookies dans la réponse du backend pour les extensions …
if (req.url ~ "(?i)\.(pdf|asc|dat|txt|…|gif|jpeg|jpg|ico|swf|css|js)(\?.*)?$") {
unset beresp.http.set-cookie;
} # GraceMode, délivre un extension de la TTL dans le cas ou le backend ne réponds plus…
set beresp.grace = 6h;
}
VARNISH
© SQLI Enterprise – SQLI GROUP | 2015 30
# On ajoute une entête à la réponse
sub vcl_deliver {
if (obj.hits > 0) {
set resp.http.X-Varnish-Cache = "HIT";
}
else {
set resp.http.X-Varnish-Cache = "MISS";
}
}
VARNISH
© SQLI Enterprise – SQLI GROUP | 2015 31
# Dans le cas d’une erreur, l’on peux afficher un message « User Fiendly » # (sans solliciter le backend) # N’existe plus en VCL4, remplacé par vcl_synth sub vcl_error {
set obj.http.Content-Type = "text/html; charset=utf-8";
synthetic {"
<html>
<head> <title>Page Unavailable</title><style>…</style> </head>
<body onload="setTimeout(function() { window.location = '/' }, 5000)"> <div id="page"> <h1 class="title">Page Unavailable</h1>
<p>The page you requested is temporarily unavailable.</p> <p>We're redirecting you to the <a href="/">homepage</a> in 5 seconds.</p>
<div class="error">(Error "} + obj.status + " " + obj.response + {")</div> </div> </body>
</html>
"};
return (deliver);
}
VARNISH
© SQLI Enterprise – SQLI GROUP | 2015 32
Instruction Varnish 3 Instruction Varnish 4
error return( synth(error_code,message))
remove unset
vcl_fetch vcl_backend_response
req.backend.healthy std.healthy(resp.backend_hint) *
req.request req.method
session_linger timeout_linger
client.port std.port(client.ip) *
server.port std.port(server.ip) *
* Nécessite le VMOD Standard (import std;)
LES PLUS / LES MOINS
+ Les plus
+ Support du Streaming
+ Support des ESI
+ Bien intégré au monde PHP
(Symfony2, Drupal, eZPublish)
- Les moins
- Pas de support HTTPS
- Outillage payant ( VAC, … )
VARNISH
© SQLI Enterprise – SQLI GROUP | 2015 34
LES PLUS, LES MOINS
CONCLUSION / QUESTIONS
+ C’est à vous !
CONCLUSION / QUESTIONS
© SQLI Enterprise – SQLI GROUP | 2015 36
LIKEZ & SUIVEZ-NOUS !
Digital that works.
WWW.SQLI-ENTERPRISE.COM