[Summer Camp] Etape 5 : Mise en cache avec Varnish

19 October 2011 | par | tuto, unix

Oct
19

varnish

On a une infra haute dispo, mais pas encore vraiment haute perf. Pour y passer, on va utiliser Varnish qui mettra en cache les pages de notre site ! Ce n’était pas prévu au planning initial que j’ai posé une nuit très tard… Mais c’est un MUST !

Varnish sera situé entre le load balancer et les frontaux (qu’il load balancera). Sont fonctionnement est simple :

  1. Je reçois une requête pour la page X
  2. L’ai-je dans mon cache ?
  3. Si oui je fournis == je soulage un frontal et les bases de X requêtes
  4. Si non je récupère et je la cache si possible (on ne peut pas cacher les pages d’utilisateur logé par exemple)

Il est cependant vrai qu’en environnement de production, on mettra les caches devant les load balancer afin d’éviter de charger les load balancer pour rien. Leur load balancing se fera alors en Round-Robin DNS.

Vous allez voir, c’est simple et efficace ! Je vais montrer pour une des deux VM, la deuxième sera une copie conforme.

Prérequis :

Nous allons donc utiliser dans ce tuto deux machines sous FreeBSD 8.2 (load balancer par le load balancer) :

  • 4 vCPU
  • 1024Mo de RAM
  • Un disque de 40Go pour un site “normal”
  • 1 cartes réseau : une sur le VLAN LB-FRONT

Installation de Varnish :

La version de varnish dans les ports de FreeBSD est à jour, nous allons donc l’utiliser ! Avant tout on s’assure d’avoir des ports bien à jour :

oaf-prj-cache# portsnap fetch && portsnap extract && portsnap update

Puis on installe Varnish :

oaf-prj-cache# cd /usr/ports/www/varnish
oaf-prj-cache# make install && make clean

Et voilà… C’est bon…

Configuration de Varnish :

Varnish utilise un langage de configuration très puissant nommé “VCL” pour Varnish Configuration Language (pas très original). Tous les fichier .vcl dans le répertoire de configuration (/usr/local/etc/varnish/) sont interprétés.

Voici dont un fichier, commenté comme d’habitude, en guise d’explications :

oaf-prj-cache# vim test.fr.vlc
 
#On défini nos frontaux
backend web01 {
   #On défini le hostname...
  .host = "oaf-srv-web01";
   #...le header sur lequel matcher...
  .host_header = "test.fr";
   #...le port d'écoute...
  .port = "80";
   #...le nobre de connexion pour le front...
  .max_connections = 5000;
   #...le timeout des sessions...
  .connect_timeout = 60s;
   #...le timeout après l'initiation de la session...
  .first_byte_timeout = 6s;
   #...le timeout entre deux paquets...
  .between_bytes_timeout = 6s;
}
 
#...Idem pour le deuxième frontal...
backend web02 {
  .host = "oaf-srv-web02";
  .host_header = "test.fr";
  .port = "80";
  .max_connections = 5000;
  .connect_timeout = 60s;
  .first_byte_timeout = 6s;
  .between_bytes_timeout = 6s;
}
 
#Puis on crée le groupe de front load balancé
director test_fr {
        {
                .backend = web01
        }
        {
                .backend = web02
        }
}
 
#Pour matcher sur toute les requêtes et augmenter la cachabilite, on réécrit les header
sub vcl_recv {
 
  if (req.http.host ~ "(?i)^localhost$") {
  set req.http.host = "test.fr";
  set req.backend = test_fr;
  }
 
  if (req.http.host ~ "(?i)^12.34.56.78$") {
  set req.http.host = "test.fr";
  set req.backend = test_fr;
  }
 
  if (req.http.host ~ "(?i)^test.fr$") {
  set req.http.host = "test.fr";
  set req.backend = test_fr;
  }
 
  if (req.http.host ~ "(?i)^test.fr$") {
  set req.http.host = "test.fr";
  set req.backend = test_fr;
  }
 
  if (req.backend.healthy) {
                set req.grace = 30s;
        } else {
                set req.grace = 1h;
  }
 
  if (req.url ~ "\.(.flv|js|css|jpg|jpeg|ico|png|gif|tgz|bz2|tbz|mp3|ogg|swf)$") {
    return (lookup);
  }
 
  if (req.http.Range) {
    return(pipe);
  }
 
  # Add a unique header containing the client address LOG
  remove req.http.X-Forwarded-For;
  set    req.http.X-Forwarded-For = client.ip;
}
 
#On défini ce que l'on peut cacher
sub vcl_fetch {
 
  if (req.url ~ "\.(flv|js|css|jpg|jpeg|ico|png|gif|tgz|bz2|tbz|mp3|ogg|swf)$") {
  set beresp.ttl = 2h;
  unset beresp.http.set-cookie;
  return (deliver);
  }
 
  #On defini la durée de vie du cache
  set beresp.ttl = 1h;
  set beresp.grace = 2h;
  return (deliver);
 
}
 
sub vcl_hit {
 
        # Le force-refresh met à jour le cache
        if (req.http.Cache-Control ~ "no-cache") {
                # Ignore requests via proxy caches, IE users and badly behaved crawlers
                # like msnbot that send no-cache with every request.
                if (! (req.http.Via || req.http.User-Agent ~ "bot|MSIE")) {
                        set obj.ttl = 0s;
                        return (restart);
                }
        }
 
        return (deliver);
}

Et voilà !

Il ne reste plus qu’à ajouter les entrés au fichier host :

oaf-prj-cache# echo "192.168.10.10       oaf-srv-web01" >> /etc/hosts
oaf-prj-cache# echo "192.168.10.11       oaf-srv-web02" >> /etc/hosts

On ajoute le service en démarrage automatique au lancement du sytème :

oaf-prj-cache# echo 'varnishd_enable="YES"' >> /etc/rc.conf

Pour finir on fait pointer les load balancer sur les varnish, mais ça vous savez déjà faire !

A lire aussi :

  1. [Summer Camp] Infra Web Haute Disponibilité
  2. [Summer Camp] Etape 4 – Load balancing HAPROXY et stunnel
  3. [Summer Camp] Étape 1 – Frontaux Web (Nginx + PHP5)
  4. [Summer Camp] Etape 3.1 – MySQL Réplication
  5. [Summer Camp] Etape 3.2 – MySQLProxy : Split Read/Write

Rédigé par

IT pro et passionné d'UNIX âgé de 22 ans, je cherche à partager quelques points de vu et mon savoir faire. N'hésitez pas à laisser un commentaire ou votre avis, ça enrichira le débat !

Une réponse to “[Summer Camp] Etape 5 : Mise en cache avec Varnish”

Afficher / Masquer les commentaires

Laisser un commentaire