<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Geekfault &#187; pistache</title>
	<atom:link href="http://geekfault.org/author/pistache/feed/" rel="self" type="application/rss+xml" />
	<link>http://geekfault.org</link>
	<description>If it doesn&#039;t segfault, you&#039;re doing it wrong.</description>
	<lastBuildDate>Sun, 16 Oct 2011 00:54:46 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Maildir mbox &#8211; La migration</title>
		<link>http://geekfault.org/2010/04/09/maildir-mbox-la-migration/</link>
		<comments>http://geekfault.org/2010/04/09/maildir-mbox-la-migration/#comments</comments>
		<pubDate>Fri, 09 Apr 2010 17:16:18 +0000</pubDate>
		<dc:creator>pistache</dc:creator>
				<category><![CDATA[internet]]></category>
		<category><![CDATA[Logiciel]]></category>
		<category><![CDATA[Non classé]]></category>
		<category><![CDATA[e-mail]]></category>
		<category><![CDATA[HowTo]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[mail]]></category>
		<category><![CDATA[maildir]]></category>
		<category><![CDATA[mbox]]></category>
		<category><![CDATA[pam_mail.so]]></category>
		<category><![CDATA[planet-libre]]></category>

		<guid isPermaLink="false">http://geekfault.org/?p=2754</guid>
		<description><![CDATA[Traditionellement, les serveurs UNIX utilisent mbox pour stocker les mails. Pour mbox, chaque dossier de votre boîte mail (Reçu, Envoyés, Archive, Corbeille, etc) est representé par un fichier, ou tout les mails sont enregistrés à la suite, séparés par une ligne vide. Ce format, très simple à utiliser, pose de nombreux problèmes. Premièrement, on ne [...]
<h3>Si vous avez aimé ce post...</h3><ol>
<li><a href='http://geekfault.org/2010/04/09/filtrer-ses-mails-un-cauchemard/' rel='bookmark' title='Filtrer ses mails ! Un cauchemard !'>Filtrer ses mails ! Un cauchemard !</a></li>
<li><a href='http://geekfault.org/2009/05/16/rsnapshot/' rel='bookmark' title='Mise en place d&#8217;un système de backup avec Rsnapshot'>Mise en place d&#8217;un système de backup avec Rsnapshot</a></li>
<li><a href='http://geekfault.org/2009/05/19/migration-de-geekfault/' rel='bookmark' title='Migration de Geekfault'>Migration de Geekfault</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p><a href="http://geekfault.org/wp-content/uploads/2010/04/illustration-maildir.jpg" title="illustration-maildir" rel="lightbox.2754"><img style=' float: left; padding: 4px; margin: 0 7px 2px 0;' align="left"   src="http://geekfault.org/wp-content/uploads/2010/04/illustration-maildir-300x270.jpg" alt="" title="illustration-maildir" width="300" height="270" class="alignleft size-medium wp-image-3040" /></a>
<p>Traditionellement, les serveurs UNIX utilisent <a href="http://fr.wikipedia.org/wiki/Mbox">mbox</a> pour stocker les mails. Pour mbox, chaque dossier de votre boîte mail (Reçu, Envoyés, Archive, Corbeille, etc) est representé par un fichier, ou tout les mails sont enregistrés à la suite, séparés par une ligne vide.</p>
</p>
<p>Ce format, très simple à utiliser, pose de nombreux problèmes. Premièrement, on ne peut pas faire d&#8217;accès parallèles, même sur des mails différents, puisque le fichier est le même (problème de verrou). Deuxièment, les serveurs POP/IMAP (comme Dovecot) ont souvent un support limité de mbox. Dovecot est obligé de placer un mail &#8220;interne&#8221; dans la boîte, pour garder l&#8217;arborescence et l&#8217;organisation des dossiers. Courier ne supporte pas mbox.</p>
<p>L&#8217;avantage principal de mbox, c&#8217;est le fait qu&#8217;il soit très répandu. Il est supporté par tout les MUA (mailutils/mail, bsd-mailx, mutt, emacs, Kmail, thunderbird, evolution). Mais les problèmes récurrents qu&#8217;il pose ont poussé <a href="http://en.wikipedia.org/wiki/Daniel_J._Bernstein">le principal développeur de qmail</a> a créer un nouveau format : <a href="http://fr.wikipedia.org/wiki/Maildir">Maildir</a>.</p>
<p><!--more--></p>
<h3>Maildir</h3>
<p>Avec Maildir, chaque mail est <b>un</b> fichier, et chaque dossier de la boîte mail, un répertoire. Attention, c&#8217;est un peu plus compliqué que ça. Les mails ne sont pas directement enregistrés dans <b>boîte/mail</b> :</p>
<ul>
<li>Le <a href="http://fr.wikipedia.org/wiki/Mail_Delivery_Agent">MDA</a> enregistre le mail dans <b>boîte/tmp/unique</b> (&#8220;unique&#8221; est un nom de fichier unique généré a partir de données pseudo-aléatoires)</li>
<li>Une fois que le mail est écrit, le MDA le déplace dans <b>boîte/new/unique</b></li>
<li>Le <a href="http://fr.wikipedia.org/wiki/Mail_User_Agent">MUA</a> le déplace dans <b>boîte/cur/unique</b> une fois qu&#8217;il voit qu&#8217;un nouveau message est arrivé dans <b>boîte/new/</b></li>
</ul>
<p><b>Pourquoi ? </b>Ce comportement est utilisé pour éviter que le MUA voit un mail incomplet (car le MDA est encore en train de l&#8217;écrire), ce qui peut arriver si la machine est surchargée, si le Maildir est sur un serveur distant (NFS,FTP), voire même si le mail est gigantesque.</p>
<h3>Maildir et procmail</h3>
<p>Le but de cet article n&#8217;est pas d&#8217;expliquer comment configurer un MDA pour qu&#8217;il enregistre les mails en Maildir,  mais malgré tout je fais une petite encartade pour les gens qui utilisent procmail. Le code suivant dans /etc/procmailrc permet de dire à procmail de mettre <b>par défaut</b> (cela peut donc être supplanté par une directive contraire dans le ~/.procmailrc) :<br />
<code>DEFAULT=$HOME/Maildir/</code><br />
Aussi, si vous n&#8217;utilisez pas encore procmail je vous conseille d&#8217;y migrer rapidement :</p>
<ul>
<li>Plus besoin de toucher à la configuration du MTA pour changer les méthodes de livraison des mails</li>
<li>Les utilisateurs peuvent écrire leurs propres règles pour leurs boîtes mails (pour avoir des boîtes séparées pour certains mails, par exemple)</li>
<li>Si vous changez de MTA vous pouvez toujours garder la même configuration, à condition de dire à votre MTA d&#8217;utiliser procmail</li>
</ul>
<h3>Configuration de mutt</h3>
<p>mutt gère très bien les Maildirs, mais il faut le configurer. Dans le .muttrc, rajoutez :<br />
<code><br />
# pour dire à mutt de que mbox est un Maildir<br />
set mbox_type=Maildir<br />
# pour dire à mutt que les chemins relatifs (avec +) sont dans "~/Maildir/"<br />
set folder="~/Maildir/"<br />
# pour dire à mutt que les mails arrivent dans Maildir/<br />
set spoolfile="~/Maildir/"<br />
# les mails archivés (pas nouveau) seront envoyés dans +Mailbox<br />
# (+ est remplacé par la variable folder).<br />
set mbox="+Mailbox"</p>
<p># remplacez par votre propre choix (ce n'est pas un tutorial de la configuration de mutt)<br />
# on indique à mutt d'envoyer les mails de ~/Maildir/ dans la boîte indiquée par la variable "mbox"<br />
set move="ask-yes"</p>
<p># ce code montre la puissance de mutt (inclure des scripts shell dans sa configuration)<br />
# ouvrir tous les dossiers qu'il trouve dans ~/Maildir/<br />
mailboxes ! + `\<br />
for file in ~/Maildir/.*; do \<br />
  box=$(basename "$file"); \<br />
  if [ ! "$box" = '.' -a ! "$box" = '..' -a ! "$box" = '.customflags' \<br />
      -a ! "$box" = '.subscriptions' ]; then \<br />
    echo -n "\"+$box\" "; \<br />
  fi; \<br />
done`<br />
</code><br />
On note qu&#8217;il faut créer les boîtes mails dans ~/Maildir/, ainsi que le Maildir en lui-même (même si procmail peut le créer tout seul, et que si vous avez converti vos mbox il existe déjà). On va créer la boîtes &#8220;Mailbox&#8221; (utilisé par mutt avec <i>set mbox=&#8221;+Mailbox&#8221;</i>).<br />
<code><br />
cd # on se place dans $HOME<br />
mkdir Maildir # on crée Maildir (ça sera peut-être déjà fait)<br />
cd Maildir<br />
mkdir cur new tmp # on crée une arborescence Maildir<br />
mkdir .Mailbox # on crée une nouvelle boite<br />
cd .Mailbox<br />
mkdir cur new tmp<br />
</code><br />
On note que :</p>
<ul>
<li>La boîte principale, ou les mails entrants sont enregistrés par le MDA, est à la racine du Maildir</li>
<li>Les sous-dossiers de la boîte, <b>commencent tous par un .</b></li>
</ul>
<p>Vous pouvez maintenant démarrer mutt, et exploiter votre mbox (pour naviguer dans les boîtes, utilisez &#8220;y&#8221;)
</p>
<h3>Migrer des boîtes mbox en Maildir</h3>
<p>Pour migrer les mbox en Maildir, le script <a href="http://perfectmaildir.home-dn.net/">perfect_maildir.pl</a> est parfait, et son usage est simple :<br />
<code>./perfect_maildir.pl path_to_Maildir/ < mbox</code></p>
<h3>pam_mail.so et You have new mail</h3>
<p>Vous avez peut-être déjà remarqué que quand vous vous ouvrez un shell, vous avez un beau message "You have new mail" qui indique de nouveaux mail dans /var/mail/$USER. Cet avertissement est geré par pam_mail.so, un module de PAM qui permet de faire ça. Si on utilise Maildir il est intéressant de dire à pam_mail.so d'aller vérifier les nouveaux mails dans le Maildir. Cette configuration se fait dans <b>/etc/pam.d/</b> sous Debian et Gentoo. Tout d'abord éditer le fichier <b>login</b>, et trouver cette ligne :<br />
<code><br />
session    optional   pam_mail.so standard<br />
</code><br />
Remplacer par :<br />
<code><br />
session optional pam_mail.so standard dir=~/Maildir<br />
</code><br />
Je recommande d'effectuer aussi la manipulation pour le fichier "ssh".</p>
<p>Normalement PAM devra modifier la variable d'environnement MAIL à Maildir/, si par hasard ce comportement ne marche pas (en fonction de la configuration de PAM) il y a toujours moyen d'ajouter<br />
<code>MAIL=Maildir/</code><br />
dans /etc/environment.</p>
<h3>Faire fonctionner la commande "mail"</h3>
<p>La commande mail est le moyen le plus simple de lire ses mails sous unix. Vous constaterez probablement que votre commande mail ne marche plus (même avec MAIL=Maildir/), car elle ne supporte pas Maildir. Mais il y a plusieurs versions de cette commande, la plus répandue étant celle de bsd (bsd-mailx avec Debian). Je vous conseille d'installer <a href="http://heirloom.sourceforge.net/mailx.html">une autre version</a>, appellée "heirloom-mailx" (sous Debian), voire "nail", qui supporte très bien les Maildir.<br />
<img src="http://pistaches.net/~pistache/stuff/maildir.png"/></p>
<h3>Liens relatifs</h3>
<ul>
<li><a href="http://wiki.dovecot.org/MailLocation/Maildir">Configurer Maildir et Dovecot</a></li>
<li><a href="http://linux.die.net/man/8/pam_mail">man pam_mail</a></li>
<li><a href="http://cr.yp.to/proto/maildir.html">la première spécification de Maildir</a> (a changé depuis)</li>
</ul>
<p>Ironiquement j'ai trouvé beaucoup de mes renseignements sur <a href="http://bugs.debian.org/">bugs.debian.org</a> :</p>
<ul>
<li><a href="http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=421010">libpam-modules: pam_mail doesn't set MAIL enviroment variable when .hushlogin exists.</a></li>
<li><a href="http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=109279">login.defs: QMAIL_DIR problems</a></li>
</ul>
<p><h3>Si vous avez aimé ce post...</h3><ol>
<li><a href='http://geekfault.org/2010/04/09/filtrer-ses-mails-un-cauchemard/' rel='bookmark' title='Filtrer ses mails ! Un cauchemard !'>Filtrer ses mails ! Un cauchemard !</a></li>
<li><a href='http://geekfault.org/2009/05/16/rsnapshot/' rel='bookmark' title='Mise en place d&#8217;un système de backup avec Rsnapshot'>Mise en place d&#8217;un système de backup avec Rsnapshot</a></li>
<li><a href='http://geekfault.org/2009/05/19/migration-de-geekfault/' rel='bookmark' title='Migration de Geekfault'>Migration de Geekfault</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://geekfault.org/2010/04/09/maildir-mbox-la-migration/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>nginx et python &#8211; le perfect setup</title>
		<link>http://geekfault.org/2010/03/01/nginx-et-python-le-perfect-setup/</link>
		<comments>http://geekfault.org/2010/03/01/nginx-et-python-le-perfect-setup/#comments</comments>
		<pubDate>Mon, 01 Mar 2010 11:47:32 +0000</pubDate>
		<dc:creator>pistache</dc:creator>
				<category><![CDATA[internet]]></category>
		<category><![CDATA[Logiciel]]></category>
		<category><![CDATA[fastcgi]]></category>
		<category><![CDATA[gunicorn]]></category>
		<category><![CDATA[http]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[nginx]]></category>
		<category><![CDATA[planet-libre]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[serveur]]></category>
		<category><![CDATA[unix]]></category>
		<category><![CDATA[web]]></category>
		<category><![CDATA[wsgi]]></category>

		<guid isPermaLink="false">http://geekfault.org/?p=2272</guid>
		<description><![CDATA[Python est devenu assez à la mode, pour le développement web, ces dernières années avec l&#8217;arrivée de frameworks web comme Django, Pylons et web.py. On le voit souvent utilisé sur apache2, avec mod_python, ou sur des serveurs Python dediés à ça (CherryPy, etc) Je cherche depuis longtemps un moyen de faire du Python sur HTTP. [...]
<h3>Si vous avez aimé ce post...</h3><ol>
<li><a href='http://geekfault.org/2011/03/24/devbox-kvmlibvirt-perfect-setup/' rel='bookmark' title='Devbox KVM+Libvirt perfect setup.'>Devbox KVM+Libvirt perfect setup.</a></li>
<li><a href='http://geekfault.org/2010/04/09/maildir-mbox-la-migration/' rel='bookmark' title='Maildir mbox &#8211; La migration'>Maildir mbox &#8211; La migration</a></li>
<li><a href='http://geekfault.org/2010/04/09/filtrer-ses-mails-un-cauchemard/' rel='bookmark' title='Filtrer ses mails ! Un cauchemard !'>Filtrer ses mails ! Un cauchemard !</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p><a href="http://geekfault.org/2010/03/01/nginx-et-python-le-perfect-setup/nginx_logo/" rel="attachment wp-att-2406"><img style=' float: left; padding: 4px; margin: 0 7px 2px 0;' align="left"   src="http://geekfault.org/wp-content/uploads/2010/03/nginx_logo-300x206.gif" alt="" title="nginx_logo" width="300" height="206" class="alignleft size-medium wp-image-2406" /></a></p>
<p><strong>Python est devenu assez à la mode, pour le développement web, ces dernières années avec l&#8217;arrivée de frameworks web comme </strong><a title="Django" href="http://djangoproject.com/"><strong>Django</strong></a><strong>, </strong><a title="Pylons" href="http://pylonshq.com/"><strong>Pylons</strong></a><strong> et </strong><a title="webpy" href="http://webpy.org"><strong>web.py</strong></a><strong>. On le voit souvent utilisé sur apache2, avec mod_python, ou sur des serveurs Python dediés à ça (CherryPy, etc)</strong></p>
<p>Je cherche depuis longtemps un moyen de faire du Python sur HTTP. J&#8217;ai mis pas mal de temps mais je pense avoir trouvé une configuration sympa.</p>
<p>Je vous propose ici d&#8217;essayer <a title="nginx" href="http://nginx.org/">nginx</a>, un serveur HTTP (entre autres), très performant et  <strong>beaucoup</strong> plus léger/rapide que apache2. Il est très efficace pour faire du reverse-proxy (c&#8217;est à dire être utilisé en frontal/load-balancer devant un serveur HTTP, et lui transmettre les requêtes en faisant du cache et le cas échéant du load-balancing).</p>
<p><!--more--></p>
<p>La configuration de nginx est très simple, et la documentation est très complète : <a href="http://wiki.nginx.org/Main">wiki.nginx.org</a>. L&#8217;installation de nginx est facile, il est inclus dans la plupart des distributions actuelles, donc à vos emerge/apt-get.</p>
<p> <code>apt-get install nginx</code>
<p>nginx ne gère pas le python nativement. Il y a plusieurs solutions cependant :</p>
<ul>
<li>Faire du proxy vers un serveur qui gère le python, comme apache2. On perd la majeure partie de l&#8217;intêret de nginx, cependant.</li>
<li>Faire du FastCGI vers un serveur FastCGI. C&#8217;est la solution la plus fréquente, en utilisant fcgi.py ou <a title="Flup" href="http://trac.saddi.com/flup">flup</a></li>
<li>Faire du WSGI. C&#8217;est un protocole de communication entre serveurs HTTP et applications Python. Solution aussi assez fréquente.</li>
<li>Faire du proxy vers un serveur qui gère le python de manière <strong>native</strong>. C&#8217;est une solution moins fréquente mais très pratique.</li>
</ul>
<p>Avant même de penser à choisir une des solutions ici présentes, il faut les comparer entre elles.</p>
<p><strong><br /> </strong></p>
<p><strong> </strong></p>
<p><strong> </strong></p>
<p><strong> </strong></p>
<h4>nginx =&gt; apache2 =&gt; python</h4>
<p>L&#8217;ennui de cette solution c&#8217;est : apache2. Utiliser nginx pour forwarder à apache2 est presque inutile. Presque ? Oui, car on peut dire à nginx de garder les fichiers statiques pour lui. Cependant, le gain de cette méthode est assez minime, et ce n&#8217;est intéressant que pour faire du load balancing sur plusieurs apaches.</p>
<p><strong><br /> </strong></p>
<p><strong> </strong></p>
<p><strong> </strong></p>
<p><strong> </strong></p>
<h4>le FastCGI</h4>
<p>FastCGI c&#8217;est une norme, pour faire traiter du contenu dynamique par une application externe. Donc le support du FastCGI tout seul est inutile, il faut aussi quelque chose pour gérer derrière.</p>
<p>J&#8217;ai testé <a href="http://trac.saddi.com/flup">flup</a>, un framework Python léger. Le résultat : ça marche, méééé c&#8217;est lent. Je tournais autour de 35/50 requêtes par seconde, et l&#8217;utilisation en mémoire vive était phénoménale, 150 mégas pour 1000 requêtes. (bien sur ces chiffres n&#8217;auront de valeur que lorsqu&#8217;ils seront comparés aux autres).</p>
<p>FastCGI est sympa pour faire une configuration &#8220;vite&#8221;. C&#8217;est d&#8217;ailleurs la seule solution viable, à ma connaissance pour faire du PHP sur nginx, à part le proxy vers un autre serveur HTTP.</p>
<p>Bref, FastCGI ne m&#8217;a pas convaincu. Et mes tests avec les autres solutions m&#8217;ont donné raison. Toujours avec moi ? On passe au WSGI !</p>
<p><strong><br /> </strong></p>
<p><strong> </strong></p>
<p><strong> </strong></p>
<p><strong> </strong></p>
<h4>le WSGI</h4>
<p> <em>WSGI is the Web Server Gateway Interface. It is a specification for web servers and application servers to communicate with web applications (though it can also be used for more than that). It is a Python standard, described in detail in PEP 333.</em>
<p>le WSGI, c&#8217;est le standard pour le Web Python. Il n&#8217;y a qu&#8217;à consulter <a title="WSGI" href="http://wsgi.org">wsgi.org</a> pour se rendre compte que c&#8217;est tout un monde. Il consiste en un ensemble de normes (nom de variables, par exemple) pour permettre au serveur d&#8217;exécuter  un fichier codé en Python.</p>
<p>Le standard pour le WSGI sur les serveurs HTTP grand public, c&#8217;est le mod_wsgi de apache2. Il a été porté sur nginx, mais c &#8216;est une #@!## infame, qui ne marche que sur les vieilles versions et qui n&#8217;a pas été mise à jour depuis bientôt 2 ans et demi (cf. <a href="http://hg.mperillo.ath.cx/nginx/mod_wsgi/">hg.mperillo.ath.cx/nginx/mod_wsgi/</a>). J&#8217;ai obtenu des performances d&#8217;environ 133 requêtes par seconde avec, ce qui est déjà mieux que FastCGI, pour ceux qui suivent <img src='http://geekfault.org/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> . Par contre, dès que j&#8217;ai voulu avancer un peu avec (toucher à la configuration, et surtout, passer à une version supérieure de nginx), j&#8217;ai été confronté à ses limites (et aux #@!## de faute de frappe dans le code source)</p>
<p>D&#8217;autant plus que l&#8217;auteur de mod_wsgi pour apache2 et l&#8217;auteur de mod_wsgi pour nginx reconnaissent ses limitations, respectivement <a href="http://blog.dscpl.com.au/2009/05/blocking-requests-and-nginx-version-of.html">ici</a> et <a href="http://blogg.ingspree.net/blog/2007/11/24/nginx-mod-wsgi-vs-fastcgi/">ici</a>. Le premier document est très intéressant pour comprendre un peu l&#8217;architecture de nginx et ses différences avec apache2. En effet, le mod_wsgi pour nginx a été codé à partir de celui pour apache2, et il subit les différences d&#8217;architecture entre apache2 et nginx.</p>
<p>Attention, je ne remet absolument pas à cause le WSGI ici, juste l&#8217;implémentation de mod_wsgi dans nginx.</p>
<p>Parce que justement, un projet super récent, c&#8217;est&#8230;. uWSGI ! uWSGI sert à combler le manque de support du WSGI dans nginx, en rajoutant un module, meilleur que mod_wsgi. Il nécessite donc de recompiler nginx. Il y a encore une autre solution, nommée gunicorn, qui ne nécessite pas de recompiler nginx. C&#8217;est un serveur HTTP minimal qui gère le WSGI nativement. uwsgi offre plus de fonctionalitées que gunicorn, mais gunicorn a l&#8217;air assez dynamique (dans le développement), et est plus facile à utiliser (pas de recompilation, support de Django natif). Au niveau des performances, je me suis amusé à faire cette comparaison :</p>
<p> </p>
<p><div class="wp-caption alignnone" style="width: 434px"><img title="Comparaison des performances entre uwsgi et gunicorn en fonction du niveau de parallélisme" src="http://pistaches.net/~pistache/stuff/patch1.png" alt="Comparaison des performances entre uwsgi et gunicorn en fonction du niveau de parallélisme" width="424" height="313" /><p class="wp-caption-text">Comparaison des performances entre uwsgi et gunicorn en fonction du niveau de parallélisme</p></div>
<p> </p>
<p>On constate plusieurs choses :</p>
<ul>
<li>Les performances augmentent en utilisant 2 workers à la place d&#8217;un, mais au delà, le gain est ridicule, puis inexistant. Le nombre 2 est dépendant du nombre de coeurs de la machine, et le nombre de workers à utiliser ne sera pas le même sous un bi-socket octocore, bien évidemment. Les meilleures performances étaient obtenues en utilisant gunicorn+3workers.</li>
<li>La différence est vraiment minime, gunicorn est en moyenne légèrement au dessus de uwsgi.</li>
<li>Ces tests sont réalisés sur une application <strong>Django</strong>. Les performances augmentent en utilisant des frameworks plus légers comme <strong>web.py</strong>, bien évidemment.</li>
</ul>
<p>uwsgi dispose de plus de fonctionalitées, comme par exemple une interface d&#8217;administration de serveur wsgi dans Django. Je vais ici expliquer l&#8217;installation et la configuration des deux solutions.</p>
<p>Ici je vais couvrir l&#8217;installation et la configuration de uwsgi et gunicorn avec <strong>Django</strong> et <strong>web.py</strong>, même si c&#8217;est bien sur adaptable avec d&#8217;autres frameworks supportant le <strong>wsgi </strong>(liste sur <a href="http://wsgi.org/wsgi/Frameworks">wsgi.org/wsgi/Frameworks</a>).</p>
<h3>Installation et configuration de <strong>uwsgi</strong></h3>
<p><strong><br /> </strong></p>
<h4>Sous Debian :</h4>
<p>1) Rajouter les dépots source, par exemple :</p>
<p> <code>deb-src http://ftp.gr.debian.org/debian/ squeeze main contrib non-free</code>
<p>2) Télécharger la source</p>
<p> <code>apt-get source nginx<br />
tar -zxvf nginx_*.orig.tar.gz<br />
cd nginx-*<br />
tar -zxvf nginx_*.debian.tar.gz</code>
<p>2) Télécharger uwsgi</p>
<p> <code>cd ..</p>
<p>wget http://projects.unbit.it/downloads/uwsgi-0.9.4.2.tar.gz</p>
<p>tar -zxvf uwsgi-0.9.4.2.tar.gz</code>
<p>3) Modifier le paquet source de nginx pour y ajouter uwsgi. Il faut éditer le fichier nginx-*/debian/rules, trouver le bloc qui commence par ./configure et ou se trouvent toutes les options de compilation, et y ajouter</p>
<p> <code>--add-module=$(CURDIR)/../uwsgi-0.9.4.2/nginx/</code>
<p>$(CURDIR)/../uwsgi-0.9.4.2/nginx/ est le chemin vers le dossier du module dans la source de uwsgi</p>
<p>4) maintenant, dans le dossier de la source de nginx, faites (pas besoin de root) :</p>
<p> <code>dpkg-buildpackage</code>
<p>5) installer le .deb généré ainsi (en tant que root maintenant)</p>
<p> <code>dpkg -i ../nginx-*.deb</code>
<p>6) Dernière étape : compiler uWSGI (le binaire en lui-même, qui va communiquer avec nginx par le biais du module)</p>
<p> <code>cd ../uwsgi-0.9.4.2/ &amp;&amp; make &amp;&amp; make install &amp;&amp; cp uwsgi_params /etc/nginx/</code>
<p>Cette dernière commande (le cp uwsgi_params&#8230;) sert à placer un fichier de configuration du module uwsgi exemple dans le repertoire de nginx.</p>
<h4>Sous les autres distributions :</h4>
<p>Il faut télécharger la source de nginx et de uwsgi, compiler nginx avec le module uwsgi (dans le répertoire nginx de la source de uwsgi), puis compiler uwsgi.﻿</p>
<p>On a maintenant un serveur uWSGI et un nginx avec  le module uwsgi. Il va maintenant falloir dire à nginx de transférer les requêtes au serveur uWSGI, avec une commande uwsgi_pass. Par exemple, dans la section server d&#8217;un de vos vhost (/etc/nginx/sites-enabled/default, par exemple, sous Debian) :</p>
<p> <code>location / {<br />
include uwsgi_params;<br />
uwsgi_pass unix:///tmp/uwsgi.sock;<br />
}</code>
<p>Il faut ensuite créer une application WSGI, par exemple, pour le framework web.py :</p>
<p> <code>import web</p>
<p>urls = (<br />
    '/.*', 'hello',<br />
    )</p>
<p>class hello:<br />
    def GET(self):<br />
        return "Hello, world."</p>
<p>application = web.application(urls, globals()).wsgifunc()<br />
applications = {'/': application }</code>
<p>Pour Django :</p>
<p> <code>import django.core.handlers.wsgi<br />
application = django.core.handlers.wsgi.WSGIHandler()<br />
applications = {'/': application }</code>
<p>Nommez ce fichier wsgi.py et placez le dans le repertoire ou vous allez placer votre code (pour Django, dans le repertoire du projet, évidemment).  Si vos nerfs n&#8217;ont pas encore lâché ici, allez prendre une petite pause de 5 minutes à titre préventif, et reprenez.  Maintenant, on va démarrer un serveur uWSGI. Placez vous dans le répertoire de votre fichier wsgi.py, et faites :</p>
<p> <code>uwsgi -s /tmp/uwsgi.sock -C -w wsgi -p2 -L</code>
<p>Explications : le -s indique ou placer le socket (ça pourrait aussi être une adresse au format hôte:port, pour un usage distant). Le -w wsgi indique de charger le fichier wsgi(.py), le -p2 indique de démarrer 2 processus, et le -L désactive l&#8217;envoi des requêtes à stdout (=&gt;flood).</p>
<p>Si vous allez à l&#8217;adresse de votre serveur web, vous devriez voir votre application Python en face de vous ! Vous voilà en train d&#8217;utiliser <strong>nginx+uwsgi+python</strong>.</p>
<p>En annexe, je rappelle que uwsgi est aussi utilisable avec apache et lighttpd.</p>
<p>Aussi, dans le dossier source de uwsgi, vous trouverez des templates pour un module d&#8217;administration de Django, à installer dans le repertoire des templates de l&#8217;administration de Django (si, si).</p>
<h3>Installation et configuration de gunicorn</h3>
<p>gunicorn est <strong>carrèment</strong> plus facile à installer. Il est codé en python, donc pas de compilation, seulement un <strong>easy_install</strong> :</p>
<p> <code>easy_install gunicorn</code>
<p>La configuration est tout aussi facile, il suffit de cela dans la configuration du vhost dans nginx :</p>
<p> <code>location / {<br />
proxy_pass http://unix:/tmp/gunicorn.sock<br />
}</code>
<p>On démarre ensuite gunicorn. Pour Django, gunicorn dispose d&#8217;un support intégré, il vous suffit de vous placer dans le répertoire de votre projet, puis :</p>
<p> <code>gunicorn_django -b unix:/tmp/gunicorn.sock --workers=2</code>
<p>Pour web.py, il faut créer un module :</p>
<p> <code>import web</p>
<p>urls = (<br />
    '/.*', 'hello',<br />
    )</p>
<p>class hello:<br />
    def GET(self):<br />
        return "Hello, world."</p>
<p>application = web.application(urls, globals()).wsgifunc()</code>
<p>Il faut ensuite démarrer le serveur Gunicorn. En étant dans le repertoire ou se trouve le module web.py (le fichier donc le code vient avant, là, au-dessus, oui), :</p>
<p> <code>gunicorn -b unix:/tmp/gunicorn.sock --workers=2 wsgi</code>
<p>Je vous invite à consulter ce lien : <a href="http://gunicorn.org/tuning.html"><span style="color: #000000;">gunicorn.org/tuning.html</span></a>, pour vous permettre d&#8217;augmenter les performances de gunicorn.</p>
<h3>Annexe</h3>
<h4><span style="font-weight: normal;">Fichiers statiques</span></h4>
<p> <code>location /admin-media {alias /usr/lib/pymodules/python2.5/django/contrib/admin/media;}</p>
<p>location /static {root /var/www/byteflow;}</code>
<p>Ces deux lignes, à rajouter après le &#8220;location /&#8221; avec uwsgi_pass ou proxy_pass (selon votre configuration) indiquent à nginx de traiter les fichiers statiques directement. Il faut bien évidemment adapter à votre configuration.</p>
<h4><span style="font-weight: normal;">Munin</span></h4>
<p><span style="font-weight: normal;">Vous pouvez trouver des plugins nginx pour munin <a href="http://muninexchange.projects.linpro.no/?search=&amp;cid=54&amp;pid=51">ici</a>. Je n&#8217;ai pas trouvé de plugin munin pour uwsgi/gunicorn, mais je pourrais peut-être en faire un si je trouve le temps.</span></p>
<h4><span style="font-weight: normal;">Plusieurs serveurs</span></h4>
<p><span style="font-weight: normal;">Si par hasard vous avez plusieurs serveurs gunicorn/uwsgi répartis sur plusieurs machines , vous pouvez les utiliser en déclarant une section </span></p>
<p> <code><span style="font-weight: normal;">upstream <em>nom</em> {} </span></code>
<p><span style="font-weight: normal;">dans nginx, contenant les adresses des serveurs distant (hôte:port ou emplacement du socket) et en utilisant &#8220;<em>nom</em>&#8221; comme argument à <em>uwsgi_pass</em> et <em>proxy_pass</em>.</span></p>
<h3>Conclusion</h3>
<p>Ces deux architectures sont très pratiques pour faire tourner du python dans un serveur web, ici nginx. uwsgi dispose de plus de fonctionalités, mais la plupart (template d&#8217;admin Django, memory profiling) pourraient facilement être ajoutées à gunicorn, qui est beaucoup plus léger à installer/configurer/maintenir (2 commandes et 3 lignes de configuration dans nginx). J&#8217;ai les deux personellement sur mon serveur, j&#8217;ai eu à alterner entre les deux pour écrire cet article, et c&#8217;est pas bien dur, un daemon à arrêter, un autre à démarrer, et changer une ligne dans la configuration de nginx.</p>
<h4>Liens</h4>
<p><a href="http://wsgi.org">wsgi.org</a></p>
<p><a href="http://gunicorn.org/">gunicorn.org/</a></p>
<p><a href="http://projects.unbit.it/uwsgi/">projects.unbit.it/uwsgi/</a></p>
<p><a href="irc://irc.freenode.org/#gunicorn">irc.freenode.org/#gunicorn</a></p>
<p><a href="http://nginx.org/">nginx.org/</a></p>
<p><a href="http://djangoadvent.com/">djangoadvent.com/</a></p>
<p><a href="http://www.django-fr.org/">www.django-fr.org/</a></p>
<p><a href="http://www.djangoproject.com/">www.djangoproject.com/</a></p>
<p><a href="http://webpy.org/">webpy.org/</a></p>
<p>Je tiens à remercier la communauté Geek{node|fault}, le chan irc #gunicorn, les développeurs de gunicorn qui sont très aimables, ainsi que Amandarn qui m&#8217;a aidé pour certains détails.</p>
<p><h3>Si vous avez aimé ce post...</h3><ol>
<li><a href='http://geekfault.org/2011/03/24/devbox-kvmlibvirt-perfect-setup/' rel='bookmark' title='Devbox KVM+Libvirt perfect setup.'>Devbox KVM+Libvirt perfect setup.</a></li>
<li><a href='http://geekfault.org/2010/04/09/maildir-mbox-la-migration/' rel='bookmark' title='Maildir mbox &#8211; La migration'>Maildir mbox &#8211; La migration</a></li>
<li><a href='http://geekfault.org/2010/04/09/filtrer-ses-mails-un-cauchemard/' rel='bookmark' title='Filtrer ses mails ! Un cauchemard !'>Filtrer ses mails ! Un cauchemard !</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://geekfault.org/2010/03/01/nginx-et-python-le-perfect-setup/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
	</channel>
</rss>

