# Configurer le serveur applicatif (Gunicorn) — đŸ”” ConfirmĂ© [Gunicorn](https://gunicorn.org/) est le serveur qui exĂ©cute l’application Django en production. Il reçoit les requĂȘtes HTTP (directement, ou via Nginx ou la plateforme d’hĂ©bergement), les confie Ă  Django et renvoie les rĂ©ponses. Il est indispensable en production, oĂč le serveur de dĂ©veloppement de Django (`runserver`) ne doit pas ĂȘtre utilisĂ©. Gunicorn permet notamment : - de **servir plusieurs visiteurs en mĂȘme temps**, en rĂ©partissant les requĂȘtes entre plusieurs processus ; - de **garder le site disponible**, en relançant automatiquement un processus qui plante ou ne rĂ©pond plus. Il ne rend pas le chargement d’une page plus rapide en soi, mais ses rĂ©glages dĂ©terminent combien de requĂȘtes le site peut traiter Ă  la fois : ils jouent donc sur la rĂ©activitĂ© du site lorsqu’il reçoit beaucoup de visites, et sur la mĂ©moire utilisĂ©e par le serveur. Sites Conformes fournit une configuration prĂȘte Ă  l’emploi : **la plupart des instances n’ont rien Ă  rĂ©gler**. Cette page explique son fonctionnement et comment l’adapter, notamment lorsque la mĂ©moire du serveur est limitĂ©e. (ou-se-trouve-la-configuration)= ## OĂč se trouve la configuration La configuration se trouve dans le fichier [`gunicorn.conf.py`](https://github.com/numerique-gouv/sites-conformes/blob/main/gunicorn.conf.py) Ă  la racine du dĂ©pĂŽt. Gunicorn le charge **automatiquement** lorsqu’il est lancĂ© depuis ce dossier, quel que soit le mode de dĂ©ploiement : `Procfile` sur Scalingo, `entrypoint.sh` avec Docker, service systemd ou `just run_gunicorn`. Les valeurs de ce fichier peuvent ĂȘtre modifiĂ©es par des variables d’environnement `GUNICORN_*` (voir [RĂ©glages](#reglages-gunicorn)), sans toucher au code. :::{note} Les options passĂ©es **en ligne de commande** Ă  Gunicorn sont prioritaires sur le fichier `gunicorn.conf.py`. Par exemple, l’exemple de service systemd de la page {doc}`serveur-linux` passe `--workers 3` : cette valeur remplace alors `GUNICORN_WORKERS`. Ordre de prioritĂ©, du plus faible au plus fort : 1. `gunicorn.conf.py` (et donc les variables `GUNICORN_*` qu’il lit) ; 2. la variable `GUNICORN_CMD_ARGS`, si elle est dĂ©finie ; 3. les options de la ligne de commande. ::: ## Fonctionnement Gunicorn s’organise en deux niveaux : ```text Processus maĂźtre (surveille, ne traite aucune requĂȘte) │ │ Worker 1 Worker 2 ← processus indĂ©pendants, (copie de l’application) (copie de l’application) chacun sa mĂ©moire │ │ │ │ thread thread thread thread ← requĂȘtes traitĂ©es en mĂȘme temps ``` - Le **processus maĂźtre** dĂ©marre les workers, les surveille et en relance un s’il plante ou ne rĂ©pond plus. - Les **workers** sont des processus Python complets, qui contiennent chacun une copie de Django, de Wagtail et du code du site. Ce sont eux qui traitent les requĂȘtes. - Les **threads** permettent Ă  un worker de traiter plusieurs requĂȘtes en mĂȘme temps. Le nombre de requĂȘtes traitĂ©es simultanĂ©ment est donc : **nombre de workers × nombre de threads**. :::{tip} En Python, un seul thread d’un processus exĂ©cute du code Ă  un instant donnĂ©. Les threads n’accĂ©lĂšrent donc pas le calcul d’une page : ils sont utiles pendant les **attentes** (requĂȘtes Ă  la base de donnĂ©es, appels Ă  un service externe), pendant lesquelles un autre thread peut avancer. Ils ne servent que si le site reçoit souvent plusieurs requĂȘtes en mĂȘme temps. ::: ### Chargement anticipĂ© de l’application La configuration active `preload_app` : le processus maĂźtre charge l’application **une seule fois**, puis crĂ©e les workers en se dupliquant. Les workers dĂ©marrent ainsi plus vite, ce qui accĂ©lĂšre les dĂ©ploiements et les redĂ©marrages. Au dĂ©part, les workers partagent la mĂ©moire du processus maĂźtre. En Python, ce partage diminue au fil du temps, car le simple fait d’utiliser un objet le modifie en mĂ©moire. Il faut donc compter qu’à terme, le processus maĂźtre et chaque worker occupent chacun une copie de l’application. (reglages-gunicorn)= ## RĂ©glages | Variable | RĂŽle | DĂ©faut | Effet sur la mĂ©moire | | --- | --- | --- | --- | | `GUNICORN_WORKERS` | Nombre de workers. À dĂ©faut, `WEB_CONCURRENCY` est utilisĂ© (dĂ©finie automatiquement par Scalingo). | `2` | **Fort** : chaque worker ajoute une copie complĂšte de l’application. | | `GUNICORN_THREADS` | Nombre de threads par worker, c’est-Ă -dire de requĂȘtes qu’un worker traite en mĂȘme temps. | `1` | **Fort sous charge** : chaque requĂȘte en cours occupe de la mĂ©moire pendant la gĂ©nĂ©ration de la page. | | `GUNICORN_TIMEOUT` | DĂ©lai (en secondes) au-delĂ  duquel un worker qui ne rĂ©pond plus est redĂ©marrĂ©. | `120` | Aucun. | | `GUNICORN_MAX_REQUESTS` | Nombre de requĂȘtes traitĂ©es par un worker avant qu’il soit redĂ©marrĂ©. | `10000` | **BĂ©nĂ©fique** : remet rĂ©guliĂšrement la mĂ©moire du worker Ă  zĂ©ro. | | `GUNICORN_MAX_REQUESTS_JITTER` | AlĂ©a ajoutĂ© Ă  `GUNICORN_MAX_REQUESTS`, pour que les workers ne redĂ©marrent pas tous en mĂȘme temps. | `2500` | Aucun. | Deux rĂ©glages sont fixĂ©s dans le code et ne dĂ©pendent d’aucune variable : - `worker_class = "gthread"` : workers capables d’utiliser des threads ; - `preload_app = True` : chargement anticipĂ© de l’application (voir ci-dessus). ## MĂ©moire et taille du serveur La mĂ©moire utilisĂ©e par Gunicorn dĂ©pend surtout du nombre de workers et du nombre de requĂȘtes traitĂ©es en mĂȘme temps : ```text mĂ©moire ≈ processus maĂźtre + workers × (application + requĂȘtes simultanĂ©es par worker × mĂ©moire par requĂȘte) ``` La mĂ©moire nĂ©cessaire varie selon la taille du site et le contenu des pages. À titre d’exemple, sur une instance de production hĂ©bergĂ©e sur un conteneur Scalingo de 1 Go, avec 2 workers : | Threads par worker | RequĂȘtes simultanĂ©es | MĂ©moire constatĂ©e | | --- | --- | --- | | 4 | 8 | environ 800 Mo, plus du swap : la limite Ă©tait atteinte | | 2 | 4 | environ 300 Ă  520 Mo selon le trafic, avec par moments un peu de swap | | 1 | 2 | environ 450 Mo, sans swap | Avec 2 threads, la mĂ©moire dĂ©passe dĂ©jĂ  par moments 512 Mo : ce rĂ©glage convient Ă  un conteneur de 1 Go, mais pas Ă  un conteneur de 512 Mo. C’est pourquoi la valeur par dĂ©faut de `GUNICORN_THREADS` est `1` : elle convient aussi aux petits conteneurs (512 Mo et moins). ### Recommandations - **Gardez les valeurs par dĂ©faut** tant que le site fonctionne correctement. - **Si la mĂ©moire approche de la limite ou si le serveur utilise du swap**, rĂ©duisez d’abord le nombre de workers, par exemple `GUNICORN_WORKERS=1` sur un petit conteneur. - **Si le site est lent sous forte affluence** et que la mĂ©moire le permet, augmentez progressivement `GUNICORN_THREADS` ou `GUNICORN_WORKERS`, puis surveillez la mĂ©moire pendant quelques heures de trafic normal. - AprĂšs chaque changement, comparez la mĂ©moire **juste aprĂšs le redĂ©marrage** et **aprĂšs une Ă  deux heures de trafic** : les threads n’occupent de mĂ©moire que lorsque plusieurs requĂȘtes arrivent en mĂȘme temps. ## Modifier un rĂ©glage ### Sur Scalingo DĂ©finissez la variable, puis **redĂ©marrez l’application** : la modification d’une variable n’est prise en compte qu’au dĂ©marrage suivant. Depuis le tableau de bord Scalingo, ajoutez ou modifiez la variable dans l’onglet **« Environnement »** de votre application (voir {doc}`scalingo`), puis redĂ©marrez l’application depuis le tableau de bord. En ligne de commande, l’équivalent est : ```sh scalingo --app mon-site env-set GUNICORN_THREADS=1 scalingo --app mon-site restart ``` Pour revenir Ă  la valeur par dĂ©faut : ```sh scalingo --app mon-site env-unset GUNICORN_THREADS scalingo --app mon-site restart ``` La mĂ©moire de l’application se suit dans le tableau de bord, onglet **« Metrics »**, graphique **« Memory – web »** (mĂ©moire, swap et limite du conteneur). ### Sur un serveur Linux ou avec Docker Ajoutez la variable au fichier `.env` de l’instance : ```sh GUNICORN_THREADS=1 ``` Puis redĂ©marrez l’application, par exemple `sudo systemctl restart sites-conformes` avec le service dĂ©crit dans {doc}`serveur-linux`. VĂ©rifiez aussi que la commande qui lance Gunicorn ne passe pas la mĂȘme option en ligne de commande, qui serait prioritaire (voir [OĂč se trouve la configuration](#ou-se-trouve-la-configuration)). ## Voir aussi - {doc}`variables-environnement`, section « Serveur applicatif (Gunicorn) » ; - la [documentation de Gunicorn](https://docs.gunicorn.org/en/stable/settings.html) pour la liste complĂšte des rĂ©glages ; - la [taille des conteneurs Scalingo](https://doc.scalingo.com/platform/internals/container-sizes).