% Copyright (c) 2004-2010 Evolix <info@evolix.fr>
%  Permission is granted to copy, distribute and/or modify this document
%  under the terms of the GNU Free Documentation License, Version 1.2
%  or any later version published by the Free Software Foundation;
%  with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
%  A copy of the license is included at http://www.gcolpart.com/howto/fdl.html

\chapter{Varnish}

Site officiel: \url{https://www.varnish-cache.org/}

\section{Présentation}

Varnish est un reverse proxy HTTP dans le but premier est la mise en cache de
contenu. Il est également capable de gérer plusieurs backend, avec
répartition de charge et détection de panne.

Varnish, développé en C, se concentre principalement sur la performance sur des infrastructures
à haut et très haut trafic.

Un autre point fort est son langage de configuration, qui permet de paramétrer
finement le comportement de Varnish aux différentes étapes du traitement de la
requête.

Le développement de Varnish a commencé en 2005, et il est distribué sous licence
BSD.

\section{Installation}

Varnish est disponible dans les dépôts de Debian Squeeze en version 2.1.3. Il
existe également un backport du paquet de Wheezy, qui fournit la version 3.0.2.
Cette version apporte de nombreuses amélioration et fonctionnalité dans la
gestion du load-balancing entre les backends.

Installation du paquet:
\begin{verbatim}
# aptitude install varnish
\end{verbatim}

\section{Configuration}

Les possibilités offertes pour la configuration de Varnish sont assez vastes,
elles seront abordés par grands thèmes.

\subsection{Paramétrage de base}

Tout d'abord, il est nécessaire de renseigner quelques informations de base au
démon \texttt{varnishd}. Cette configuration se passe dans le fichier
\texttt{/etc/default/varnish}. Plusieurs cas de figure sont proposés à titre
d'exemple dans ce fichier, en voici un autre avec quelques optimisations
supplémentaires:
\begin{verbatim}
DAEMON_OPTS="-a 192.0.2.1:80 \
             -T localhost:6082 \
             -f /etc/varnish/default.vcl \
             -S /etc/varnish/secret \
             -s malloc,3G
             -s file,/var/lib/varnish/$INSTANCE/varnish_storage.bin,10G
             -p thread_pools=<Number of CPU cores>
             -p thread_pool_add_delay=2
             -p thread_pool_max=5000"
umask 022
\end{verbatim}

Et voici quelques explications sur les paramètres:
\begin{description}
  \item[\texttt{-a 192.0.2.1:80}] \hfill \\
    Il s'agit du couple IP,port sur lequel Varnish attendra les requêtes HTTP à
    traiter.
  \item[\texttt{-T localhost:6082}] \hfill \\
    Il s'agit du couple IP,port sur lequel sera accessible l'interface
    d'administration de Varnish (traité plus loin dans ce chapitre).
  \item[\texttt{-f /etc/varnish/default.vcl}] \hfill \\
    Cette option indique le fichier de configuration à utiliser.
  \item[\texttt{-S /etc/varnish/secret}] \hfill \\
  \item[\texttt{-s malloc,3G}]
  \item[\texttt{-s file,/var/lib/varnish/\$INSTANCE/varnish\_storage.bin,10G}] \hfill \\
    On indique ici qu'une partie du cache sera stocké en mémoire 3~Go, ainsi que
    dans un fichier plat sur le disque, qui sera limité à 10~Go.
  \item[\texttt{-p thread\_pools=<Number of CPU cores>}]
  \item[\texttt{-p thread\_pool\_add\_delay=2}]
  \item[\texttt{-p thread\_pool\_max=5000}] \hfill \\
    L'option \texttt{-p} permet de modifier différents paramètres d'exécution.
    De nombreux paramètres peuvent être modifiés, la liste complète avec leur
    description se trouve ici:
    \url{https://www.varnish-cache.org/docs/2.1/reference/varnishd.html}.

    \texttt{thread\_pools} indique le nombre de groupe de threads à lancer. Cette
    valeur ne devrait pas dépasser le nombre de c\oe{}ur disponible sur le système
    (pour des raisons de performance). Pour \texttt{threa\_poo\_ad\_delay}, il
    s'agit du temps en milisecondes à attendre avant la création d'un nouveau
    thread. Et enfin \texttt{threa\_poo\_max} représente le nombre total de
    thread maximum à ne pas dépasser, tout pool confondus.
  \item[\texttt{umask 022}] \hfill \\
    Varnish s'attend à avoir un umask à 022 pour s'exécuter
    correctement. \'Etant donné qu'il n'est pas forcé dans le script d'init,
    nous le plaçons ici manuellement.
\end{description}

\subsection{Aperçu de la syntaxe du langage VCL}

\subsection{Gestion du cache}

En se positionnant entre le client et le serveur applicatif, Varnish permet de
lire et surcharger si besoin les entêtes HTTP de contrôle du cache. Par défaut,
celle ci sont lues et pris en compte, mais on peut redéfinir le comportement
dans la configuration.

Voici quelques exemples d'utilisation typique:

\paragraph{Forcer le TTL pour certains contenu}
\begin{verbatim}
sub vcl_fetch {
    if (req.url ~ "\.(png|gif|jpg)$") {
        set beresp.ttl = 5d;
        set beresp.http.magicmarker = "1";
    }
}

sub vcl_deliver {
    if (resp.http.magicmarker) {
        unset resp.http.magicmarker;
        set resp.http.Age = "0";
      }
}
\end{verbatim}
\texttt{beresp.http.magicmarker} permet de marquer l'objet pour pouvoir ensuite
remettre son age à 0 (dans \texttt{vcl\_deliver}.

Pour que le changement de TTL le soit également coté client, on réécrit le
header HTTP \emph{Cache-Control} en ajoutant (dans le premier \texttt{if}:
\begin{verbatim}
set beresp.http.cache-control = ``max-age=432000'';
\end{verbatim}

\paragraph{Indiquer si un object provient du cache ou pas dans les headers HTTP}
\begin{verbatim}
sub vcl_deliver {
        if (obj.hits > 0) {
                set resp.http.X-Cache = "HIT";
        } else {
                set resp.http.X-Cache = "MISS";
        }
}
\end{verbatim}

\subsection{Gestion du load-balancing}

Tout d'abord, il faut définir au moins un backend pour que l'ensemble puisse
fonctionner correctement. Cela se fait à l'aide de la directive
\texttt{backend}, comme ceci:
\begin{verbatim}
backend www00 {
    .host = "192.0.2.8";
    .port = "80";
}

backend www01 {
    .host = "192.0.2.14";
    .port = "80";
}
\end{verbatim}

Il est ensuite possible de grouper ces backends dans un cluster, appelé
\emph{director} dans le langage de Varnish:
\begin{verbatim}
director baz round-robin {
    { .backend = www00; }
    { .backend = www01; }
}
\end{verbatim}

Et enfin, on indique dans quel cas il sera utilisé (dans l'exemple il sera
utilisé dans tous les cas):
\begin{verbatim}
sub vcl_recv {
    if (req.http.host ~ "^.*$") {
        set req.backend = baz;
    }
}
\end{verbatim}

Il s'agit ici de la configuration la plus simple possible. Maintenant, il peut
être intéressant d'ajuster certains paramètres:
\begin{itemize}
  \item poids
  \item max connection
  \item s/round-robin/client et critères pour sticky
\end{itemize}

\subsection{Gestion du failover}

probe sur les backend
saint et grace mode

\section{Administration}

\section{Gestion des logs}
