Django-fr

Documentation Django

Comment utiliser Django avec FastCGI, SCGI or AJP

La configuration préférée actuellement est Apache avec mod_python. Toutefois, certains utilisateurs en hébergement mutualisé se voient proposer les protocoles FastCGI, SCGI ou AJP comme seules options possibles. Dans certaines offres, ces protocoles peuvent offrir une meilleure sécurité -- et probablement de meilleures performances -- que mod_python.

Note

Ce document se concentre plus particulièrement sur FastCGI. Les autres protocoles comme SCGI ou AJP sont également supportés via le paquet python flup. Référez-vous à la section "Protocoles" plus bas pour les éléments spécifiques à SCGI et AJP.

FastCGI est un moyen efficace de laisser une application externe servir des pages à un serveur Web. Le serveur Web délègue les requêtes entrantes (via une socket) à FastCGI. Celui-ci exécute le code et retourne la réponse au serveur Web. Ce dernier retourne à son tour le résultat au navigateur de l'internaute.

Avec FastCGI, et tout comme mod_python, le code est chargé en mémoire. Cela permet aux requêtes d'être traitées sans temps d'initialisation. Contrairement à mod_python (ou tout comme mod_perl), un process FastCGI n'est pas exécuté au sein d'un process du serveur Web, c'est un process autonome et persistant.

Pourquoi exécuter du code dans un process distinct ?

Le fonctionnement habituel des mod_* des langages de script dans Apache (et plus particulièrement PHP, Python et Perl) est de fonctionner au sein d'un process de votre serveur Web. Bien que cela réduise le temps d'initialisation -- puisque le code n'a pas à être lu à chaque requête -- cela a un coût au niveau de la mémoire. Par exemple, pour mod_python, chaque process Apache contient son propre interpréteur Python, ce qui utilise un montant considérable de RAM.

De part la nature de FastCGI, il est même possible de lancer des process sous des comptes utilisateurs différents de celui utilisé par le process du serveur Web. C'est très avantageux dans un environnement mutualisé, puisque cela signifie que votre code est isolé de celui des autres utilisateurs.

Prérequis : flup

Avant de pouvoir utiliser FastCGI avec Django, vous devez installer flup. Flup est une bibliothèque python qui gère FastCGI. Une version 0.5 ou supérieure est recommandée.

Démarrer votre serveur FastCGI

FastCGI fonctionne dans un mode client-serveur, et dans la plupart des cas vous allez démarrer vous-même le process FastCGI. Votre serveur (que ce soit Apache, lighttpd ou n'importe quel autre serveur) contactera votre process Django-FastCGI uniquement lorsqu'une page dynamique aura besoin d'être chargée. Puisque le service (daemon) est déjà lancé avec le code en mémoire, il va pouvoir retourner une réponse très rapidement.

Note

Si vous êtes sur un environnement mutualisé, vous serez probablement obligé d'utiliser les processus FastCGI du serveur Web. Référez-vous à la section ci-dessous pour savoir comment utiliser Django dans le cadre d'un serveur lancé via des process FastCGI.

Un serveur web peut se connecter à un serveur FastCGI de deux façons : soit en en utilisant une "domain socket" UNIX (un "named pipe" sur les systèmes Windows), soit en utilisant une socket TCP. La sélection est une affaire de préférence. La socket TCP est généralement plus simple à mettre en place au niveau des permissions.

Pour démarrer le serveur, rendez-vous dans le répertoire racine de votre projet (là où est situé votre manager.py), et exécutez manage.py avec l'option runfcgi:

./manage.py runfcgi [options]

Si vous ajoutez help comme seul paramètre après runfcgi, la liste des options disponibles sera affichée.

Vous devrez définir soit une socket, un protocol ou simultanément un hôte` et ``port. Ensuite, lors du paramétrage du serveur Web, il vous suffit de pointer sur le couple hôte/port ou sur la socket que vous avez spécifié lorsque vous avez lancé votre serveur FastCGI.

Protocoles

Django supporte les mêmes protocoles que ceux supportés par flup, c'est à dire fastcgi, SCGI et AJP1.3 (le protocole Apache JServ, en version 1.3). Choissisez le protocole de votre choix en utilisant le paramètre protocol=<protocol_name> avec ./manage.py runfcgi, où <protocole_name> est une valeur parmi : fcgi (par défaut), scgi ou ajp. Par exemple:

./manage.py runfcgi protocol=scgi

Exemples

Lancer un serveur en mode "thread" sur un port TCP:

./manage.py runfcgi method=threaded host=127.0.0.1 port=3033

Lancer un serveur en mode "prefork" sur une "domain socket" Unix:

./manage.py runfcgi method=prefork socket=/home/user/mysite.sock pidfile=django.pid

Lancer sans le service en tache de fond (utile pour débugguer):

./manage.py runfcgi daemonize=false socket=/tmp/mysite.sock maxrequests=1

Arrêter le service (démon) FastCGI

Si votre process n'est pas en tache de fond, il est aisé de l'arrêter : pressez les touches Ctrl-C pour arrêter et éteindre votre serveur FastCGI. Par contre, en utilisant les process en tâche de fond, vous devez utiliser la commande Unix kill.

Si vous spécifiez le paramètre pidfile à manage.py runfcgi, vous pouvez tuer votre service FastCGI de la façon suivante:

kill `cat $PIDFILE`

...où $PIDFILE est le pidfile que vous avez spécifié.

Pour redémarrer aisément votre service FastCGI sur Unix, essayez ce petit script:

#!/bin/bash

# Replace these three settings.
PROJDIR="/home/user/myproject"
PIDFILE="$PROJDIR/mysite.pid"
SOCKET="$PROJDIR/mysite.sock"

cd $PROJDIR
if [ -f $PIDFILE ]; then
    kill `cat -- $PIDFILE`
    rm -f -- $PIDFILE
fi

exec /usr/bin/env - \
  PYTHONPATH="../python:.." \
  ./manage.py runfcgi socket=$SOCKET pidfile=$PIDFILE

Configuration d'Apache

Pour utiliser Django avec Apache et FastCGI, vous avez besoin qu'Apache soit installé et configuré avec mod_fastcgi installé et activé. Consultez la documentation d'Apache pour plus d'information.

Une fois que cela est en place, pointez Apache sur votre instance Django FastCGI en éditant le fichier de configuration d'Apache httpd.conf. Vous devez faire deux choses :

  • Utiliser la directive FastCGIExternalServer pour indiquer la localisation de votre serveur FastCGI.
  • Utiliser mod_rewrite pour faire pointer vos urls FastCGI de façon appropriée

Indiquer la location de votre serveur FastCGI

La directive FastCGIExternalServer indique à Apache comment trouver votre serveur FastCGI. Comme l'explique la documentation de FastCGIExternalServer, vous devez indiquer une socket ou un hôte. Ci-après des exemples:

# Connect to FastCGI via a socket / named pipe.
FastCGIExternalServer /home/user/public_html/mysite.fcgi -socket /home/user/mysite.sock

# Connect to FastCGI via a TCP host/port.
FastCGIExternalServer /home/user/public_html/mysite.fcgi -host 127.0.0.1:3033

Dans les deux cas, le fichier /home/user/public_html/mysite.fcgi n'a pas à exister. C'est juste une URL interne utilisée par le serveur web -- un "hook" pour indiquer quelles requêtes à une URL donnée doivent être traitées par FastCGI (Plus de détails à ce sujet dans la section suivante).

Utilisation de mod_rewrite pour pointer vos URLs vers votre serveur FastCGI

La seconde étape est d'indiquer à Apache d'utiliser FastCGI pour les urls correspondant à un certain motif. Pour faire ceci, utilisez le module mod_rewrite et réécrivez vos URLs vers mysite.fcgi (ie, ce que vous avez défini pour la directive FastCGIExternalServer, comme expliqué précédemment).

Dans cet exemple, nous indiquons à Apache d'utiliser FastCGI pour toutes les requêtes ne correspondant pas à un fichier sur le système de fichiers et qui ne commencent pas pas /media/. Il s'agit probablement du cas le plus courant, si vous utilisez l'interface d'administration de Django:

<VirtualHost 12.34.56.78>
  ServerName example.com
  DocumentRoot /home/user/public_html
  Alias /media /home/user/python/django/contrib/admin/media
  RewriteEngine On
  RewriteRule ^/(media.*)$ /$1 [QSA,L,PT]
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteRule ^/(.*)$ /mysite.fcgi/$1 [QSA,L]
</VirtualHost>

Configuration de lighttpd

lighttpd est un serveur léger utilisé habituellement pour servir des fichiers statiques. Il supporte nativement FastCGI, et s'avère donc de fait un bon choix pour servir à la fois des contenus statiques et dynamiques, si votre site ne requiert pas explicitement Apache.

Assurez-vous que mod_fastcgi est dans votre liste de modules, quelque part après mod_rewrite et mod_access, mais avant mod_accesslog. Vous allez également vouloir mod_alias pour servir les éléments d'interface d'administration.

Ajoutez ce qui va suive dans votre fichier de configuration de lighttpd:

server.document-root = "/home/user/public_html"
fastcgi.server = (
    "/mysite.fcgi" => (
        "main" => (
            # Use host / port instead of socket for TCP fastcgi
            # "host" => "127.0.0.1",
            # "port" => 3033,
            "socket" => "/home/user/mysite.sock",
            "check-local" => "disable",
        )
    ),
)
alias.url = (
    "/media/" => "/home/user/django/contrib/admin/media/",
)

url.rewrite-once = (
    "^(/media.*)$" => "$1",
    "^/favicon\.ico$" => "/media/favicon.ico",
    "^(/.*)$" => "/mysite.fcgi$1",
)

Héberber plusieurs sites Django sur une instance de lighttpd

lighttpd vous permet d'utiliser une "configuration conditionnelle" pour personnaliser votre configuration par hôte. Pour utiliser plusieurs sites avec FastCGI, ajoutez le block conditionnel suivant autour de la configuration FastCGI de chaque site:

# If the hostname is 'www.example1.com'...
$HTTP["host"] == "www.example1.com" {
    server.document-root = "/foo/site1"
    fastcgi.server = (
       ...
    )
    ...
}

# If the hostname is 'www.example2.com'...
$HTTP["host"] == "www.example2.com" {
    server.document-root = "/foo/site2"
    fastcgi.server = (
       ...
    )
    ...
}

Vous pouvez également exécuter plusieurs instances Django sur le même site en spécifiant simplement plusieurs entrées dans la directive fastcgi.server. Ajouter une hôte FastCGI pour chacune d'entre-elles.

Héberger un projet Django sur un hébergement mutualisé avec Apache

Beaucoup d'hébergeurs mutualisés ne vous permettent pas d'exécuter vos propres services ou d'éditer le fichier httpd.conf. Dans ces cas il est quand même possible d'utiliser Django en utilisant un serveur web qui gère le lancement des processus FastCGI.

Note

Si vous utiliser un serveur web gérant les processus FastCGI, comme expliqué dans cette section, vous n'avez pas besoin de démarrer le serveur FastCGI de vous-même. Apache va générer un nombre de process, les augmentant autant que nécessaire.

Dans votre répertoire racine, ajoutez ceci dans un fichier nommé .htaccess

AddHandler fastcgi-script .fcgi
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ mysite.fcgi/$1 [QSA,L]

Ensuite, créez un petit script qui dit à Apache de recharger votre programme FastCGI. Créez un fichier mysite.fcgi et placez le dans votre répertoire web et assurez-vous qu'il soit exécutable:

#!/usr/bin/python
import sys, os

# Add a custom Python path.
sys.path.insert(0, "/home/user/python")

# Switch to the directory of your project. (Optional.)
# os.chdir("/home/user/myproject")

# Set the DJANGO_SETTINGS_MODULE environment variable.
os.environ['DJANGO_SETTINGS_MODULE'] = "myproject.settings"

from django.core.servers.fastcgi import runfastcgi
runfastcgi(method="threaded", daemonize="false")

Relancer le process fastcgi

Si vous changez le moindre bout de code python sur votre site, vous devez indiquer à FastCGI que votre code a changé. Pour autant, il n'y a pas besoin de redémarrer Apache dans ce cas. Préférez plutôt de retransférer votre fichier mysite.fcgi ou d'éditer ce fichier. Ceci afin que la date du fichier change. Quand Apache voit que le fichier a été mis à jour, il rechargera votre application Django.

Si vous avez accès à une console sur un système Unix, vous pouvez le faire simplement en utilisant la commande touch

touch mysite.fcgi

Servir les fichiers media de l'interface d'administration

Quelque soit le serveur et la configuration que vous avez décidé d'utiliser, vous ne devez pas oublier de penser à servir les fichiers media de l'interface d'administration. Les conseils donnés dans la documentation de modpython est applicable dans les configurations décrites précédemment.