Combien de processus dois-je spécifier dans un WSGIDaemonProcess lors de l'exécution de Django via mod_wsgi?


23

Disons que j'ai 2 sites (Superuser et Serverfault) fonctionnant à partir de leur propre hôte virtuel Apache sur une seule boîte. Les 2 sites sont alimentés par Django et fonctionnent sur Apache avec mod-wsgi. Un fichier de configuration typique pour l'un des sites ressemblera à ceci:

WSGIDaemonProcess serverfault.com user=www-data group=www-data processes=5

L'hôte est une machine Linux avec 4 Go de RAM exécutant Ubuntu. Quelqu'un peut-il suggérer le nombre de processus que je dois spécifier ci-dessus pour mes 2 sites? Supposons qu'ils aient le même trafic que les sites Superuser et Serverfault réels.

Réponses:


22

Eh bien, la quantité de trafic ne les sites réels et Superuser ServerFault ont? Les hypothèses ne sont pas très utiles si elles n'ont pas assez d'informations pour faciliter la réponse ...

Votre nombre de processus dans le pire des cas doit être le nombre maximal de demandes par seconde que vous souhaitez que le site soit en mesure de gérer, divisé par le nombre de demandes par seconde qu'un processus peut traiter si toutes ces demandes sont effectuées à votre action la plus lente (donc l'inverse du temps de traitement de cette action). Ajoutez le facteur de fudge que vous jugez approprié, en fonction de l'intervalle de confiance de vos mesures req / sec et du temps.

Le nombre moyen de cas est le même, mais vous divisez le nombre de requêtes / s par la moyenne pondérée de vos demandes par seconde pour chaque action (le poids est le pourcentage de demandes que vous prévoyez d'atteindre cette action particulière). Encore une fois, les facteurs de fudge sont utiles.

La limite supérieure réelle du nombre de processus que vous pouvez exécuter sur la machine est dictée par la quantité de mémoire supérieure que prend chaque processus; spouler un processus, puis exécuter une variété d'actions gourmandes en mémoire (celles qui récupèrent et traitent beaucoup de données, généralement) contre lui avec un ensemble de données réaliste (si vous utilisez simplement un ensemble de données jouet pour les tests, disons 50 ou 100 lignes, puis si l'une de vos actions récupère et manipule chaque ligne du tableau, ce ne sera pas une bonne mesure pour quand ce tableau atteindra 10 000 lignes) pour voir à quoi sert l'utilisation de la mémoire. Vous pouvez restreindre artificiellement votre utilisation de la mémoire par processus avec un script qui récolte les travailleurs qui atteignent un certain seuil d'utilisation de la mémoire, au risque de provoquer des problèmes désagréables si vous définissez ce seuil trop bas.

Une fois que vous avez votre chiffre d'utilisation de la mémoire, vous déduisez une certaine quantité de mémoire pour les frais généraux du système (j'aime 512 Mo moi-même), déduisez une pile de plus si vous avez d'autres processus en cours d'exécution sur la même machine (comme une base de données), puis un peu plus pour vous assurer que vous ne manquez pas d'espace de cache disque (dépend de la taille de votre ensemble de travail de disque, mais encore une fois, j'irais avec pas moins de 512 Mo). C'est la quantité de mémoire que vous divisez par votre utilisation de mémoire par processus pour obtenir le plafond.

Si le nombre de processus dont vous avez besoin pour gérer votre charge de pointe est supérieur au nombre de processus que vous pouvez installer sur la boîte, vous avez besoin de plus de machines (ou pour déplacer la base de données vers une autre machine, dans le cas le plus simple).

Voilà, plusieurs années d'expérience dans la mise à l'échelle de sites Web distillés en un seul petit et simple message SF.


Un autre facteur important pour le nombre de processus / threads est la durée de traitement des demandes individuelles et la répartition globale sur toutes les durées possibles. En d'autres termes, combien de demandes doivent être traitées à la fois, ce qui prend un temps de réponse supérieur à la moyenne. Donc, ce n'est pas aussi simple que des requêtes théoriques / s, car l'impact de ces requêtes plus longues peut être significatif et dicter indûment les paramètres de configuration globaux. FWIW mod_wsgi 3.0 inclura une collection de statistiques intégrée pour essayer de capturer des données à ce sujet pour faciliter la configuration.
Graham Dumpleton

@Graham: Relisez ma réponse, j'ai couvert cela en détail. Les requêtes / s sont simplement l'inverse du temps de réponse, et il est plus facile de diviser par une requête entière / s que de multiplier par une décimale.
womble

Vous ne pouvez cependant pas vous concentrer uniquement sur la réponse la plus défavorable, ni uniquement sur la moyenne. Il doit être pondéré de manière basée sur le pourcentage de demandes tombant dans des périodes de temps, c'est-à-dire la répartition sur toutes les périodes possibles prises. Si vous avez vraiment pris votre temps de réponse dans le pire des cas, vous auriez des exigences irréalistes. Le problème c'est qu'il est vraiment difficile de savoir quelle formule utiliser. C'est pourquoi dans mod_wsgi 3.0, il y aura une collecte de statistiques intégrée qui examine l'utilisation des threads et pour quel pourcentage en nombre et en temps que n'importe quel nombre de threads est utilisé à un moment donné.
Graham Dumpleton

3
Le problème est peut-être que vous ne regardez les processus que là où je m'inquiète de la façon dont les threads que chaque processus utilise prennent en compte et ce n'est pas aussi simple. En d'autres termes, cette directive WSGIDaemonProcess indique 5 processus où chaque processus utilise par défaut 15 threads. Autant que j'ai lu dans votre description, cela suppose des processus à thread unique. Sinon, montrez-moi comment votre modèle répond aux threads et aux problèmes de contention / mise à l'échelle autour du GIL. Donc, qualifiez que votre description n'est valable que pour les processus à thread unique et je ne contesterai pas.
Graham Dumpleton

2
L'approche "multithread-Apache + multiprocess-wsgi" n'est-elle pas la meilleure solution tant que vous n'êtes pas sûr à 99% que votre code Python et toutes les dépendances sont thread-safe?
Tomasz Zieliński

9

la réponse de womble est impressionnante, quoique un peu difficile à comprendre et à appliquer pour les inexpérimentés. Je voudrais donner quelques chiffres empiriques et une comparaison des applications "contenu simple" et "commerce électronique".

Il n'y a pas beaucoup de matériel autour de la définition de différents cas d'utilisation par rapport à leur configuration appropriée de mod_wsgi, donc j'espère que c'est correct d'utiliser un peu de prose ici.

A) Sites CMS et microsites

Nous gérons plusieurs sites Web clients, la plupart d'entre eux principalement des sites de contenu ou des micro-sites hébergeant django CMS, certains formulaires personnalisés et parfois Celery pour les tâches d'arrière-plan planifiées. Ces sites n'ont pas faim de ressources, plusieurs d'entre eux fonctionnent heureusement en parallèle sur un seul Intel Xeon à 4 cœurs avec 32 Go de RAM. Voici la configuration que nous utilisons pour chacun de ces types de sites:

WSGIDaemonProcess example.com user=www-data processes=2 maximum-requests=100

Je parle d'environ 40 sites sur un seul serveur, la plupart d'entre eux avec leur site Staging en veille. Avec 2 processus (ayant 15 threads chacun, par défaut), les sites sont aisés, bien que limités dans leur capacité d'allocation des ressources du serveur. La raison pour laquelle cette configuration est suffisante peut être justifiée par la nature simple de l'application (CMS): aucune demande ne devrait prendre plus de quelques millisecondes. Apache restera toujours détendu, tout comme la charge CPU.

B) Sites de commerce électronique

Les sites plus complexes que nous réalisons se caractérisent par des opérations locales encore peu coûteuses en termes de calcul mais des dépendances externes (par exemple, des services Web fournissant des données de réservation) qui sont coûteuses en termes de temps de transaction. Les opérations avec des demandes externes occupent des threads beaucoup plus longtemps, vous avez donc besoin de plus de threads pour répondre au même nombre d'utilisateurs (par rapport à un simple site CMS ci-dessus). Pire encore, les threads sont parfois bloqués lorsqu'un service externe ne peut pas répondre immédiatement à une demande, parfois pendant quelques secondes. Cela peut entraîner l'effet secondaire désagréable que les threads plaçant des demandes vers la même file d'attente de service, jusqu'à ce que tous les threads mod_wsgi disponibles soient utilisés et bloqués en attente.

Pour ces scénarios, nous avons essayé d'utiliser des 6processus sans voir beaucoup de différence, et nous nous sommes retrouvés avec 12une amélioration incomparable des performances et de la stabilité opérationnelle:

WSGIDaemonProcess example.com user=www-data processes=12 maximum-requests=100

Certains tests de charge simples avec 150 et 250 utilisateurs parallèles sont facilement gérés par le site en restant bien réactifs (tandis qu'avec les 2processus, le site est inutilisable et traite 50 utilisateurs en parallèle). Les 2 CPU 6 Core Intel Xeon avec 32 Go de RAM fonctionnent bien en dessous de 25% d'utilisation du CPU sous cette charge, l'utilisation de la RAM reste presque constante à moins de 25% également. Notez que nous utilisons une machine dédiée uniquement pour un seul site ici, donc nous ne volerons pas les ressources dont d'autres sites pourraient avoir besoin.

Conclusion

L'utilisation d'un plus grand nombre de processus est un compromis entre permettre ou non à Apache d'utiliser les ressources système disponibles. Si vous voulez garder un système de serveur stable (pas un site Web!) Dans des conditions "d'attaque", gardez le nombre bas. Si vous souhaitez qu'Apache vous aide à utiliser les ressources système (CPU, RAM) en cas de besoin, choisissez un nombre plus élevé. La hauteur à laquelle vous pouvez aller calcule un peu comme indiqué dans la réponse acceptée ci-dessus, et est finalement limitée par la puissance CPU et la RAM disponibles.

(PS: je garde la section ConfigurationDirectives du wiki du projet modwsgi sous mon oreiller pour une lecture en arrière-plan comme Apache. Assurez-vous également de comprendre et de surveiller les connexions ouvertes de votre serveur Apache .)


Excellent article, mais pourquoi ne définissez-vous pas le nombre de threads? Étant donné que GIL de Python annule beaucoup des avantages des threads, je suppose que vous voudriez avoir plus de processus que de threads, mais y a-t-il un avantage à spécifier le nombre de threads?
Cerin

Le nombre par défaut threadsest 15 selon la documentation . Je ne pense pas qu'il y ait un avantage à le spécifier explicitement. En fait, je me souviens l'avoir laissé pour une raison: il y avait un article sur SO ou une partie de la documentation qui recommandait d'omettre la valeur pour éviter les effets secondaires (je sais, cela semble bizarre). Malheureusement, je ne trouve pas cette source maintenant. Pour le reste de votre question (GIL), vous êtes probablement plus expert que moi, désolé.
Peterino

Merci pour cette configuration empirique. Cependant, gardez à l'esprit que selon ce post You should never use maximum-requests in a production system unless you understand the implications and have a specific temporary need.
raratiru
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.