En l’espace de quelques jours, j’ai vu passer sous mon fil Twitter trois articles très intéressant à propos de la configuration Varnish+Apache. Pour ceux qui ne connaissent pas, Varnish est un serveur statique, fréquemment utilisé par les gros sites de journaux en ligne, notamment dans une configuration de Reverse Proxy, c’est à dire Varnish en frontend et Apache en backend. Un peu de la même façon que ce que j’ai expliqué plusieurs fois ici, où je fonctionne avec Nginx en frontend et Apache en backend.
La différence de Varnish est qu’il est un site statique par essence, et donc contrairement à Nginx, il n’est pas capable de passer par WSGI pour servir des pages non-générées. Nginx a également l’avantage de fonctionner avec une pile de connexion, et Varnish est donné comme fonctionnant avec un système de cache interne, mais je n’ai pas réussi à en voir plus dans les trois articles que j’ai lu. Les voici :
Apache, Varnish, nginx and lighttpd
Ce billet montre des comparatifs de performances, qui tendent à montrer dans des conditions assez correctes et objectives que Nginx et Varnish font jeu égal, avec un léger avantage pour Varnish.
Gérer son cache web avec Varnish
Chez HAute-Disponibilité, on peut en apprendre un peu plus sur le système de cache de Varnish, mais je ne m’y suis pas penché davantage.
Booster votre blog WordPress avec Varnish
Sur ce billet de Nicolargo, on peut comprendre comment fonctionne la configuration de Varnish. Ce billet m’a permit de faire le comparatif entre les configurations Nginx et Varnish que je vais présenter ci-dessous.
Comparatif des configurations
Pour bien comprendre la différence entre Nginx et Varnish (tous deux en frontend, sur le port 80, et servant le contenu non statique à Apache sur le port 127.0.0.1:8080), je vais copier-coller les deux configurations l’une à côté de l’autre et les expliquer.
Pour Nginx
Pour Nginx, on va avoir un seul fichier important. Ce sera celui relatif au site servi (donc le fichier de conf sera dans /etc/nginx/sites-available) :
server { listen 212.227.159.187:80; server_name monsite.fr; # On distribue les fichiers statiques directement location ~* ^.+.(jpg|jpeg|gif|css|png|js|ico|txt|srt|swf)$ { gzip_static on; root /var/www/htdocs/abricocotier.fr/; access_log /var/log/nginx/monsite-server-access.log; error_log /var/log/nginx/monsite-server-error.log; error_page 404 = /erreur-404; expires 30d; } location / { proxy_pass http://127.0.0.1:8080/; include /etc/nginx/conf.d/proxy.conf; #root /lerepertoiredemonsite/; #index index.html index.htm; } }
Tout tient dans ce fichier.
On y voir que le premier bloc d’instructions vise à dire à Nginx de traiter tous les fichiers portant les extensions classiques pour des fichiers statiques.
Le deuxième bloc dit à Nginx d’envoyer toutes les requêtes qui restent (non-traitées jusque là) sur localhost:8080.
Pour Varnish
Grâce au billet de Nicolargo, j’ai pu rapidement m’installer une configuration Varnish très simplement en local. C’est pas plus compliqué que pour Nginx.
Dans le fichier /etc/varnish/default.vcl, on met le nom du site qui sera passé au serveur de backend (donc on prend un peu le problème à revers par rapport à Nginx) :
backend www { .host = "monsite.fr"; .port = "8080"; }
Puis, à la suite, dans le même fichier, les instructions de traitement pour les requètes :
sub vcl_recv { if (req.http.host ~ "(www\.monsite\.fr|monsite\.fr)") { set req.backend = www; } # Compatiblity with Apache log remove req.http.X-Forwarded-For; set req.http.X-Forwarded-For = client.ip; # Normalize Content-Encoding if (req.http.Accept-Encoding) { if (req.url ~ "\.(jpg|png|gif|gz|tgz|bz2|lzma|tbz)(\?.*|)$") { remove req.http.Accept-Encoding; } elsif (req.http.Accept-Encoding ~ "gzip") { set req.http.Accept-Encoding = "gzip"; } elsif (req.http.Accept-Encoding ~ "deflate") { set req.http.Accept-Encoding = "deflate"; } else { remove req.http.Accept-Encoding; } } # Remove cookies and query string for real static files if (req.url ~ "^/[^?]+\.(jpeg|jpg|png|gif|ico|js|css|txt|gz|zip|lzma|bz2|tgz|tbz|html|htm)(\?.*|)$") { unset req.http.cookie; set req.url = regsub(req.url, "\?.*$", ""); } # Pas de cache pour les requêtes POST if (req.request == "POST") { return(pass); } # Pas de cache pour l'interface d'administration de WordPress if( req.url ~ "^/wp-(login|admin)" || req.http.Cookie ~ "wordpress_logged_in_" ){ return(pass); } }
Comme on le vois, ce n’est pas beaucoup plus compliqué, c’est juste que le problème est pris dans l’ordre inverse. Je pense que c’est dû au fait que Varnish est fait pour faire du reverse proxy, contrairement à Nginx, qui n’a peut-être pas été conçu juste pour ça. Mais Nginx a l’énorme avantage de fonctionner avec une pile de requête, donc je me dis qu’il présente une sécurité pour qui n’a pas un gros serveur sous la main mais peu voir affluer à certaines heures de grosses quantités de connexions (et n’ayant pas envie de voir son serveur tomber toutes les 5 minutes).
Je rajoute que le mode de configuration de Nginx est sans doute plus simple pour ceux qui ont un peu regardé la configuration sous Apache (je pense notamment à l’arborescence sites-available/ et sites-enabled/ avec lien symbolique entre les deux pour « activer » un site), et c’est donc un facteur de plus grande facilité d’utilisation.
Enfin, et en terme de performances (c’est ça qui nous intéresse), je n’ai pas réussi à trouver de comparatif clair entre les performances des configurations Nginx+Apache et Varnish+Apache. Je constate que de très gros sites utilisent Nginx+Apache (par exemple, WordPress.com et toute sa plateforme de blogs), mais j’ai l’impression que Varnish n’anonce pas clairement qu’il existe comme le fait Nginx (c’est à dire que quand on a Varnish+Apache, le header de la réponse ne comporte que Apache, donc le client ne peut pas savoir que Varnish est dans la boucle).
D’après un collègue techniquement fort (ce qui m’inciterait à le croire), Apache serait mis souvent en frontend quand on a besoin d’un serveur d’application Java en backend (Tomcat, Weblogic, Websphere, etc), car Apache sans plugin est un serveur statique. J’ai du mal à trouver de quoi étayer cette thèse sur le web, Wikipédia ne mentionnant jamais dans la fiche Apache que celui-ci est un serveur statique quand il n’a pas de plugins (même si en soit, c’est vrai : Apache sans plugin ne peut pas faire beaucoup d’autre chose que de servir des fichiers statiques). La fiche anglophone dit seulement que Apache est fait pour pouvoir servir du contenu static et dynamique. Bref : je continue à penser qu’Apache est une formidable machine à tout faire, mais qu’il y a mieux quand on prend un besoin spécifique (cela dit, Google a plusieurs fois dit qu’il utilisait une version d’Apache modifiée pour ses serveurs, donc il semble difficile de dire qu’Apache n’est pas un serveur rapide).
Bref : si un jour j’ai deux serveurs sous la mains et n’étant pas en productions, je tenterais de faire un ApacheBenchmark des deux configurations, avec un site WordPress en backend, celui-ci ayant une base de donnée correcte, afin que cela simule des conditions réelles.
Merci pour cet article. Cependant la où je comprend très bien l’intérêt d’un varnish + apache, la solution nginx + apache me dépasse totalement ! Nginx est capable de servir du contenu dynamique sans faire appel à apache, notamment via PHP-FPM (inclu depuis peu dans la source de PHP 5.3.3, mais cela était possible en 5.2.x également)
Nginx + apache reste une hérésie pour moi… Quel est l’intérêt que vous y trouvez ?
Le seul cas ou apache m’est encore indispensable, c’est pour faire tourner un serveur SVN (le mod_dav n’a pas encore d’équivalent chez Nginx)
J’aimerais beaucoup avoir votre avis sur ce sujet.
Encore merci.
Effectivement, Nginx pourrait trèsbien se passer d’Apache, à condition de parvenir à transcrire parfaitement toutes les règles de mapping Apache en règles Nginx. Malheureusement, j’utilise WP-Super-Cache, dont les règles font un mapping conditionnel, ce que je ne parviens pas à reproduire avec mon Nginx…
Effectivement… Pourquoi ne pas se passer de WP Super-cache dans ce cas et mettre en place un couple Varnish + Nginx ? Ou bien utiliser un plugin tel que DB Cache reloaded pour cacher uniquement les résultats de requête SQL.
De mon point de vue c’est la partie requête qui manque d’optimisation dans WP et qui ralenti l’ensemble. La partie PHP n’est pas si couteuse en ressource pour la génération des pages.
@Necrokeeper: C’est vrai qu’en soit, je pourrais très bien faire comme celà, et enlever le cache WP.
Mais d’une part j’ai peur que la BDD soit surchargée dans ce cas, même avec les différents systèmes de cache, et d’autre part j’aime bien l’idée que mon serveur serve des pages en cache pour 99% des visiteurs… Donc il ne me reste plus qu’à réussir à reproduire les règles de mapping dans Nginx, mais j’ai tenté plusieurs fois, sans succès…
Nginx est meilleur pour servir le contenu statique, c’est indéniable.
Par contre Apache est plus performant pour le contenu php…
Il y a des benchs très poussés qui ont été réalisés, et ils démontrent très clairement cette tendance.
C’est je pense la raison pour laquelle laisser Apache derrière Nginx est très bon choix 🙂
@Vince, je veux bien me laisser convaincre… tu sais ou je peux trouver les « benchs très poussés » dont tu parles ?
@Necrokeeper @Vince: J’ai du mal à croire que Nginx+Apache+mod_php ce soit plus rapide que Varnish+Nginx+mod_cgi+PHP… Surtout que le mod_php implique le mode d’Apache sans thread, et qu’en cas de charge, Apache deviens très vite un gros boulet…
@Louis : Je suis d’accord avec toi, et j’en ai fais les frais 🙂
Je suis d’accord avec Vince, on a du voir les même tests, celui qui compare NginX, Apache, Cherokee, Varnish, GWAN… etc. qui conclut que seul GWAN est supérieur à NginX, avec de grosses limitations qui biaisent totalement ses perfs (entre autres, pas de rewrites… bouh!), et le test qui compare Apache en statique /dynamique et NginX en statique / dynamique.
La conclusion est sans appel, la solution la plus perf à l’heure actuelle est le couple NginX (statique) + Apache (dynamique).
… Et Apache en fonctionnement standard, exit le mode CGI qui pourrit les perfs du serveur, cela va de soi 🙂
« Je rajoute que le mode de configuration de Nginx est sans doute plus simple pour ceux qui ont un peu regardé la configuration sous Apache (je pense notamment à l’arborescence sites-available/ et sites-enabled/ avec lien symbolique entre les deux pour « activer » un site), et c’est donc un facteur de plus grande facilité d’utilisation. »
Cette architecture existe sous la distribution Debian (et ses dérivés) mais elle n’est pas standard. Elle est là pour organiser la configuration pour des serveurs qui hébergeraient un très gand nombre de sites, mais elle n’est pas forcément adaptée pour l »hébergement d’un seul site. Rien ne vous oblige à ne pas insérer la configuration de votre site dans le httpd.conf
L’inclusion de fichiers de configuration externes est une fonctionalité très utile quand la configuration devient complexe. A l’inverse, pour une configuration très sommaire (un seul site servi et sans modules) le fichier de configuration est très proche en taille de deux cités plus haut, mais Apache n’a pas vocation à être utilisé de cette manière.
« car Apache sans plugin est un serveur statique. » Certes mais après sert-il mieux les pages statiques que Nginx ? J’en doute fortement !