31 votes

Comment configurer correctement Varnish pour les sites Symfony2 ?

J'ai un site web (avec ESI) qui utilise le reverse proxy de Symfony2 pour la mise en cache. La réponse moyenne est d'environ 100 ms. J'ai essayé d'installer Varnish sur le serveur pour l'essayer. J'ai suivi guide du livre de recettes Symfony étape par étape, a tout effacé dans cache mais http_cache était toujours créé lorsque je l'ai essayé. J'ai donc pensé que je pourrais essayer de commenter $kernel = new AppCache($kernel); de app.php . Ça a plutôt bien marché. http_cache n'était plus créé et par varnishstat, Varnish semblait fonctionner :

12951         0.00         0.08 cache_hitpass - Cache hits for pass
 1153         0.00         0.01 cache_miss - Cache misses

C'était sur environ 14 000 demandes, donc je pensais que tout irait bien. Mais après avoir vérifié, j'ai découvert que les réponses étaient passées à environ 2 secondes.

Apache fonctionne sur le port 9000 et Varnish sur le port 8080. J'ai donc échoué en utilisant echoping -n 10 -h http://servername/ X.X.X.X:8080 .

Je n'ai aucune idée de ce qui pourrait être mauvais. Y a-t-il des paramètres supplémentaires nécessaires pour utiliser Varnish avec Symfony2 ? Ou est-ce que je fais simplement quelque chose de mal ?


Selon les demandes, voici mon default.vcl avec les modifications que j'ai faites jusqu'à présent.

J'ai trouvé 2 problèmes avec la configuration par défaut de Varnish :

  • il ne met pas en cache les requêtes avec des cookies (et tout le monde dans mon application a une session assignée)
  • il ignore Cache-Control: no-cache en-tête

J'ai donc ajouté des conditions pour ces cas à ma configuration et elle fonctionne assez bien maintenant (~175 req/s contre ~160 avec le proxy inverse S2 - mais honnêtement, je m'attendais à un peu plus). Je n'ai aucune idée de la façon de vérifier si tout est en ordre, donc toute contribution est la bienvenue.

La plupart des pages ont un cache varié par cookie, avec s-maxage 1200. Les éléments ESI communs ne varient pas en fonction du cookie, avec s-maxage assez faible (articles, listes d'articles). Les pages de profil d'utilisateur ne sont pas du tout mises en cache ( no-cache ) et je ne suis pas vraiment sûr que les inclusions ESI sur ces derniers soient même mises en cache par Varnish. La seule ESI qui varie en fonction des cookies est l'en-tête contenant des informations spécifiques à l'utilisateur (c'est le cas sur 100% des pages).

Tout dans ce post est spécifique à Varnish 3.X (j'utilise personnellement 3.0.2).

De plus, après quelques semaines de travail, je n'ai plus aucune idée de ce que je fais, donc si vous trouvez quelque chose d'étrange dans les configurations, faites-le moi savoir.

enter image description here

18voto

exg Points 131

Je suis surpris qu'il n'y ait pas eu de réponse complète à cette question en 10 mois. Cette page pourrait être très utile.

Vous l'avez souligné vous-même :

  • Varnish ne met pas en cache les requêtes avec des cookies.
  • Varnish ignore l'en-tête Cache-Control : no-cache.

La première chose à faire est de se demander si tout le monde dans votre application a besoin d'une session. Si ce n'est pas le cas, ne lancez pas la session, ou au moins retardez-la jusqu'à ce qu'elle soit vraiment nécessaire (c'est-à-dire qu'ils se connectent ou autre).

Si vous pouvez toujours mettre les pages en cache lorsque les utilisateurs sont connectés, vous devez faire très attention à ne pas servir à un utilisateur une page qui était destinée à quelqu'un d'autre. Mais si vous voulez le faire, modifiez vcl_recv() pour supprimer le cookie de session pour les pages que vous voulez mettre en cache.

Vous pouvez facilement faire en sorte que Varnish traite la directive no-cache dans vcl_fetch() et en fait vous l'avez déjà fait.

Un autre problème que j'ai trouvé est que Symfony par défaut met max-age à 0, ce qui signifie qu'ils ne seront jamais mis en cache par la logique par défaut de vcl_fetch.

J'ai aussi remarqué que vous aviez réglé le port dans Varnish sur :

backend default {
    .host = "127.0.0.1";
    .port = "80";
}

Vous avez dit vous-même qu'Apache fonctionne sur le port 9000, ce qui ne semble pas correspondre. Vous devriez normalement configurer Varnish pour qu'il écoute sur le port par défaut (80) et configurer Varnish pour qu'il cherche le backend sur le port 9000 ou autre.

1voto

Rafael Sanches Points 926

Si c'est toute votre configuration, le vcl_recv est configuré deux fois.

Dans les pages que vous voulez mettre en cache, pouvez-vous envoyer les en-têtes de mise en cache ? C'est ce qui serait le plus logique, puisque les images ont probablement déjà les en-têtes de mise en cache d'Apache et que la logique de l'application décide des pages qui peuvent être effectivement mises en cache, mais vous pouvez aussi forcer cela dans Varnish.

Vous pourriez utiliser un vcl_recv comme ceci :

# Called after a document has been successfully retrieved from the backend.
sub vcl_fetch {

    # set minimum timeouts to auto-discard stored objects
    # set beresp.prefetch = -30s;
    set beresp.grace = 120s;

    if (beresp.ttl < 48h) {
      set beresp.ttl = 48h;}

    if (!beresp.cacheable) 
        {pass;}

    if (beresp.http.Set-Cookie) 
        {pass;}

    # if (beresp.http.Cache-Control ~ "(private|no-cache|no-store)") 
    # {pass;}

    if (req.http.Authorization && !beresp.http.Cache-Control ~ "public") 
        {pass;}

}

Celui-ci met en cache, dans varnish, uniquement les requêtes qui sont définies comme pouvant être mises en cache. Aussi, soyez conscient que votre configuration ne met pas en cache les requêtes avec des cookies.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X