Si Squid est un des proxy-caches les plus connus et les plus utilisés en forward-proxy, Apache peut être utilisé à l’identique sur des configurations qui restent “simples” mais très fonctionnelles.
L’utilisation la plus courante de mod_proxy
se fait sur un serveur frontal1 en répartissant les charges dynamiques et statiques sur des « fermes2 ». Par exemple, on redirige /images/
et /media/
sur une ferme statique avec peut-être un autre serveur Web plus approprié (nginx par exemple).
Apache joue ainsi le rôle de proxy et distribue la charge sur plusieurs serveurs, l’appellation courante est reverse-proxy.
On peut coupler le rôle de proxy avec un mécanisme de cache afin d’améliorer les performances en réduisant le nombre d’appels aux serveurs sous-jacents.
Vous noterez dans la documentation du module3 que sont évoqués plusieurs sous-modules du module de cache, correspondant au différents fournisseurs de stockage pour le cache4 (disque5, à base de cache d’objets partagés6) ainsi que des sous-modules pour les différents protocoles pouvant potentiellement profiter d’un système de cache (ftp7, http8, etc.).
La commande ProxyPass
permet d’associer un chemin (ou Location
) à un (groupe de) serveur(s) tiers, exemple :
ProxyRequests Off
ProxyPass / http://10.0.0.1/
ProxyPass /images/ http://10.0.0.10/
ProxyPass /medias/ http://10.0.0.20/
La directive ProxyRequests
sert à activer les fonctionnalités de forward-proxy d’Apache, ce dont nous n’avons pas besoin ici, ce qui explique sa désactivation en lui passant le paramètre Off
;
Les requêtes pour l’URL /
seront relayées au serveur possédant l’IP 10.0.0.1, etc.
Ici, en utilisant le sous-module mod_proxy_balancer
9, on distribue sur deux fermes de deux machines les parties statiques :
ProxyRequests Off
ProxyPass / http://10.0.0.1/
<Proxy balancer://clusterImages>
BalancerMember http://10.0.0.10:80
BalancerMember http://10.0.0.11:80
</Proxy>
<Proxy balancer://clusterMedias>
BalancerMember http://10.0.0.20:80
BalancerMember http://10.0.0.21:80
</Proxy>
ProxyPass /images/ balancer://clusterImages/
ProxyPass /medias/ balancer://clusterMedias/
Pour une gestion distante du sous-module mod_proxy_balancer
on peut rajouter (attention à la sécurité10 !) :
<Location /balancer-manager>
SetHandler balancer-manager
Require ip 10.0.0.1
</Location>
On se servira ici de la directive proxy_pass
.
Dans la configuration de votre virtualhost :
location / {
include proxy_params;
proxy_pass http://127.0.0.1;
}
Pour distribuer la charge sur plusieurs machines, on utilise la directive upstream
en dehors de la configuration du virtualhost, donc du server {…}
:
upstream loadbalancing {
server 10.0.0.1;
server 10.0.0.2;
}
Et on utilisera l’upstream ainsi défini dans le virtualhost :
location / {
include proxy_params;
proxy_pass http://loadbalancing;
}
On l’a vu plus haut, il existe différents sous-modules de cache. Il vous faudra en activer un pour bénéficier des mécanismes de cache d’Apache.
Prenons l’exemple de mod_cache_disk
:
a2enmod cache_disk
systemctl restart apache2
systemctl start apache-htcacheclean
Dans votre virtualhost :
CacheQuickHandler off
<Location />
CacheEnable disk
</Location>
La directive CacheQuickHandler
est généralement à positionner à off
. En effet, si elle est à on
, sa valeur par défaut, les directives de restrictions d’accès (Require
) ne seront pas appliquées.
On peut aussi spécifier l’URL pour laquelle il faut activer le cache directement en argument de la directive CacheEnable
:
CacheEnable disk /foo/
NB : Nginx ne peut cacher que sur disque, pas en mémoire. On peut néanmoins tricher en le faisant cacher sur un montage tmpfs11 ou en mamaillant avec memcached
.
Définissez un espace de cache en dehors de votre virtualhost, donc du server {…}
:
proxy_cache_path /var/cache/nginx keys_zone=my_zone:10m inactive=7d max_size=700m;
De nombreux arguments12 sont utilisables avec cette directive mais nous n’en verrons que quelques-uns (la documentation du module vous tend les bras).
Notons d’abord les indispensables :
/var/cache/nginx
: il s’agit du chemin du répertoire de cache (donc bien évidemment complètement modifiable) ;keys_zone=name:size
: le nom de la zone de cache. Nginx permet donc de définir différents caches, réutilisables à loisir dans différents endroits de la configuration. La taille de cet argument n’est pas la taille du cache, mais la taille de la mémoire allouée pour conserver les métadonnées des données cachées.Les arguments optionnels :
inactive=time
: les données cachées non consultées durant ce délai seront supprimées du cache ;max_size=size
: il s’agit de la taille maximale du dossier de cache. Lorsque cette taille est dépassée, les données les plus anciennes sont supprimées pour faire de la place aux nouvelles.On utilisera ensuite cette zone de cache ainsi dans un virtualhost (ou juste dans le location, voire en dehors du virtualhost) :
location / {
proxy_cache my_zone;
…
}
Il n’y a pas que le cache côté serveur qui améliore les performances, il y a aussi le cache côté client !
Si certaines applications se chargent de renvoyer toutes seules des en-têtes contenant des instructions pour le cache client, il est parfois necéssaire de les mettre soi-même.
Avec Apache, on pourra utiliser indifféremment le module mod_expires
13 ou le module mod_headers
14 :
<Directory /var/www/site/css/>
ExpiresActive On
ExpiresDefault "access plus 1 month"
</Directory>
<Directory /var/www/site/js>
Header add Cache-Control "public, max-age=2678400"
</Directory>
Avec Nginx, c’est semblable, on utilisera la directive expires
ou add_header
:
location /css {
expires 1M;
}
location /js {
add_header Cache-Control "public, max-age=2678400";
}
Varnish est un reverse-proxy cachant dont les performances sont impressionnantes15 et dont la mise en œuvre est fort simple pour une utilisation basique.
Installez Varnish, configurez-le pour qu’il utilise votre serveur Apache (voir dans le fichier /etc/varnish/default.vcl
, changez le port du backend pour le port 80
) et redémarrez-le.
Alourdissez la page servie par votre serveur sur http://localhost/
avec la commande truncate
:
truncate -s 500M /var/www/html/index.html
Lancez les commandes suivantes :
wget http://localhost/ -O /tmp/index.html
wget http://localhost:6081/ -O /tmp/index.html
wget http://localhost:6081/ -O /tmp/index.html
Vous constaterez aisément que Varnish (qui écoute par défaut sur le port 6081) améliore grandement les performances tout en réduisant l’utilisation des ressources de votre machine, sauf bien évidemment lors de sa première requête puisqu’il n’a pas encore le fichier en cache.
Pro tips :
varnishd -Cf /etc/varnish/default.vcl
;NB : Varnish cache par défaut en mémoire, mais il peut aussi cacher sur disque.
Ce n’est parce que Nginx est plus véloce dans notre cas, même sans cache, qu’il faut l’employer partout. Le fait de pouvoir étendre les capacités d’Apache de façon simple et dynamique grâce aux modules en font un allié précieux dans bien des cas. « Tout ressemble à un clou pour qui ne possède qu’un marteau ». Vous avez plusieurs outils à votre disposition, faites-en bon usage pour la bonne raison.
Un montage pertinent et une configuration idoine vous permettront d’encaisser des charges bien plus importantes, voire carrément impressionnantes16 !
On considérera que Nginx écoute sur le port 81 et Apache sur le port 80 (installez les deux sur la même machine et modifiez-en la configuration).
Dans /etc/nginx/nginx.conf
, ajoutez :
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=cache:10m inactive=7d max_size=700m;
Dans /etc/nginx/sites-enabled/default
, ajoutez :
server {
listen 81;
listen [::]:81;
location / {
include proxy_params;
proxy_pass http://127.0.0.1/;
proxy_cache cache;
proxy_cache_valid 12h;
expires 12h;
proxy_cache_use_stale error timeout invalid_header updating;
}
}
Bien évidemment, si vous faites écouter apache sur un autre port que le 80, ajoutez le port à l’adresse de la directive proxy_pass
.
Lancez les commandes suivantes :
siege -c 300 --time=20s http://localhost/
siege -c 300 --time=20s http://localhost:81/
Comparez les performances.
Supprimez la configuration ajoutée ayant trait au cache (tout ce qui commence par proxy_cache
et expires
) et redémarrez Nginx.
Recommencez. Que constatez-vous ?
Dans le virtualhost qui tourne sur le port 81 dans /etc/nginx/sites-enabled/default
, remplacez le location /
:
location / {
try_files $uri $uri/ =404;
}
Relancez Nginx.
Relancez le benchmark
Que constatez-vous, que ce soit pour les performances pures (hits, nombre de transactions par secondes, etc.) ou sur l’impact sur la charge de votre machine ?
Choisissez un module de cache (disque ou mémoire) et activez-le22.
Refaites le benchmark de http://localhost
(utilisez les valeurs de l’Apache non configuré comme cache ou comme proxy des exercices précédents pour comparer). Que constatez-vous ?
Un serveur qui encaisse les requêtes entrantes et les transmet à un ou plusieurs autres serveurs↩
groupes de serveurs applicatifs fournissant le même service de manière équivalente et distribuable↩
http://httpd.apache.org/docs/2.4/mod/mod_cache_socache.html↩
http://httpd.apache.org/docs/2.4/fr/mod/mod_proxy_http.html↩
http://httpd.apache.org/docs/2.4/fr/mod/mod_proxy_balancer.html↩
ne laissez pas tout le monde accéder à quelque chose qui peut modifier le comportement de votre serveur↩
http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_cache_path↩
true story↩
il ne faut pas non plus négliger les possibilités de caching des applications servies. Un bon plugin sur Wordpress peut tout changer↩
raccourcisseur d’URLs, https://lstu.fr↩
et on lit la doc sur http://httpd.apache.org/docs/2.4/en/mod/mod_cache.html siouplaît↩