Lighttpd est un très bon serveur web mais force est de constater qu’il est difficile de se passer d’apache (en particulier à cause des fichiers .htaccess qui ne sont pas supportés par Lighttpd). Nous allons donc voir comment mettre en place un serveur Lighttpd qui servira du contenu statique et dynamique tout en faisant office de proxy pour Apache quand l’utilisation de ce dernier est nécessaire.
Vue d’ensemble de la solution
- Lighttpd écoutera sur le port 80 et répondra donc à toutes les requêtes, il servira de reverse-proxy pour les requêtes destinées à Apache.
- Apache écoutera sur le port 8080, il répondra à toutes les requêtes sur ce port. En production, il ne devrait appelé que par Lighttpd mais il sera possible de l’appeller depuis n’importe quel navigateur pendant une phase de Debug.
- La configuration sera adaptable pour chaque VirtualHost, il sera envisageable de mettre en place 3 configurations différentes :
- uniquement Lighttpd, dans le cas d’un site statique ou dynamique pouvant fonctionner sous Lighttpd, cette configuration est à privilegier
- contenu statique servi par Lighttpd, contenu dynamique servi par Apache via le mod_proxy de Lighttpd. Cette solution est à utiliser pour améliorer les performances d’un site nécessitant Apache pour son contenu dynamique.
- site uniquement servi par Apache via le mod_proxy de Lighttpd. Cette solution n’est envisagée que pour des cas particuliers, elle est à éviter a priori.
Modification de la configuration d’Apache
Afin que le serveur Apache écoute sur le port 8080, il faut modifier la directive Listen 80 en Listen 8080 de son fichier de configuration. Il faura aussi modifier les configuration des différents VirtualHost pour qu’ils soient pris sur le port 8080. Enfin, vu qu’en fonctionnement nominal, le serveur ne sera interrogé que sur du contenu dynamique et page par page, on pourra désactiver le KeepAlive en plaçant la directive KeepAlive Off.
Configuration de base de Lighttpd
La configuration de Lighttpd est en général effectuée dans un seul fichier lighttpd.conf. Dans notre cas, nous avons besoin d’activer les modules suivants :
- mod_proxy : ce module permettra de faire fonctionner Lighttpd en tant que reverse-proxy.
- mod_status : ce module nous permettra de suivre l’état du serveur
- mod_auth : ce module permettra de limiter l’accès au server-status
Pour ajouter un module, il suffit de décommenter la ligne contenant le nom du module dans le fichier de configuration.
Pour activer le server-status, il suffit d’ajouter la directive suivante :
status.status-url = "/server-status"
Il est quand même plus sur de limiter l’accès au server-status, il faut créer un fichier .htpasswd avec les identifiants et mot de passes des utilisateurs autorisés à se connecter au server-status (l’executable htpasswd d’Apache convient parfaitement pour cette tâche). il faut ensuite ajouter les lignes suivantes à la configuration de Lighttpd (dans mon cas, le fichier .htpasswd est stocké dans le dossier /usr/local/www) :
auth.backend = "htpasswd"
auth.backend.htpasswd.userfile = "/usr/local/www/.htpasswd"
auth.require = ( "/server-status" =>
(
"method" => "basic",
"realm" => "status",
"require" => "valid-user"
)
)
On peut ajouter une petite optimisation : l’utilisation d’un cache pour les appels stat :
server.stat-cache-engine = "fam"
Ajout d’un VirtualHost servi uniquement par Lighttpd
C’est le cas le plus simple et a priori le plus performant, il faut néanmoins être sur que l’application web hébergée sur le VirtualHost est totalement compatible avec Lighttpd.
$HTTP"host" =~ "test.labs.fr" { server.document-root = "/home/majinboo/sites/test" accesslog.filename = "/var/log/lighttpd/test-access.log" }
Ajout d’un VirtualHost Mixte : contenu statique servi par Lighttpd et contenu dynamique sous Apache
Ce blog est propulsé par Dotclear, n’ayant que peu de retour sur la compatibilité de Dotclear avec Lighttpd, j’ai pour l’instant choisi de le faire fonctionner en configuration mixte. La stratégie est la suivante : pour qu’Apache soit appelé sur les URL non-statiques (qui sont la plupart du temps rewritées) on utilise un proxy uniquement pour les url qui ne terminent pas par une extension connue pour être celle d’un fichier statique.
Vu que le contenu sera servi pour moitié par Apache et pour l’autre moitié par Lighttpd, il faut configurer le virtualHost à la fois dans Apache et dans Lighttpd. Ce qui donne pour la configuration d’Apache quelque chose de relativement anodin :
<VirtualHost *:8080>
ServerAdmin majinboo@labs.fr
DocumentRoot "/home/majinboo/sites/blog.majinboo.org"
ServerName majinboo.org
ServerAlias www.majinboo.org
ServerAlias blog.majinboo.org
ErrorLog "/var/log/httpd/majinboo.org-error.log"
CustomLog "/var/log/httpd/majinboo.org-access_log" combined
</VirtualHost>
Pour Lighttpd, la configuration est un poil plus complexe en raison de l’utlisation du mod_proxy :
$HTTP"host" =~ "majinboo.org" { server.document-root = "/home/majinboo/sites/blog.majinboo.org" accesslog.filename = "/var/log/lighttpd/majinboo.org-access.log" $HTTP"url" !~ "\.(js|css|gif|jpg|png|ico|txt|swf|html|htm)$" { proxy.server = ( "" => ( ( "host" => "127.0.0.1", "port" => 8080 ) ) ) } }
Ajout d’un VirtualHost entièrement managé par Apache
Cette configuration peut par exemple être utile dans le cas d’un WebService qui sert des images générées par un script (captcha ou autre). Dans ce cas il faudra mettre la configuration du VirtualHost dans la configuration d’Apache et se contenter de tout rediriger vers Apache dans la configuration de Lighttpd, ce qui donne :
$HTTP"host" =~ "test2.labs.fr" { server.document-root = "/home/majinboo/sites/captchaServer" accesslog.filename = "/var/log/lighttpd/captcha-access.log" proxy.server = ( "" => ( ( "host" => "127.0.0.1", "port" => 8080 ) ) ) }
Petit test de performances
Le test consiste à lancer siege en mode benchmark avec une liste d’URLs correspondant à la page d’accueil de ce blog. Pour ce test, 150 utilisateurs concurrents déroulent la liste d’URLs de manière séquentielle pendant 10 minutes. Le serveur qui est testé est un Bi Xeon Dual Coeurs avec 4 GB de RAM.
Résultats avec Apache
- Nombre de requêtes par seconde : 148
- Load du serveur : 50
- Mémoire libre : 2GB
Résultats avec la configuration mixte Lighttpd / Apache
- Nombre de requêtes par seconde : 151
- Load du serveur : 20
- Mémoire libre : 2.3 GB
On remarque que les performances brutes ne sont pas significativement meilleures avec Lighttpd, cependant le serveur est bien moins chargé avec la configuration mixte. Il est possible que ce soit la machine de test qui limite (une dédibox première génération).
Possibilités d’amélioration qui feront l’objet d’un futur article
Pour l’instant, le mod_proxy de Lighttpd interroge Apache à chaque requête. Un patch permet d’ajouter un mod_cache à Lighttpd qui permettrait d’augmenter les performances de la solution en servant le résultats de certaines requêtes destinées à Apache depuis un cache.
De plus PHP et postGreSQL qui sont utilisés par le blog ne sont pour l’instant pas optimisés. Il serait opportun d’optimiser leur configuration et d’ajouter le module eAccelerator à PHP.