7
votes

Que se passe-t-il lorsque vous avez une boucle infinie dans le code de la vue Django?

Quelque chose que je viens de penser à:

Dites que j'écris le code de vue pour mon site Django, et je fais une erreur et crée une boucle infinie.

Chaque fois que quelqu'un essaierait d'accéder à la vue, le travailleur affecté à la demande (que ce soit un travailleur gevent ou un fil python) resterait dans une boucle indéfiniment.

Si je comprends correctement, le serveur enverrait une erreur de délai d'attente au client après 30 secondes. Mais que se passera-t-il avec le travailleur python? Continuera-t-il de fonctionner indéfiniment? Cela semble dangereux!

Imagine J'ai un serveur dans lequel j'ai alloué 10 travailleurs. Je le laisse courir et à un moment donné, un client essaie d'accéder à la vue avec la boucle infinie. Un travailleur y sera assigné et sera effectivement mort jusqu'au redémarrage du serveur suivant. La chose dangereuse est qu'au début, je ne le remarquerais pas, car le site serait tout simplement plus lent, ayant 9 travailleurs au lieu de 10. Mais cela pourrait se reproduire encore et encore pendant une longue période de temps, peut-être des mois. Le site deviendrait progressivement plus lent, jusqu'à ce qu'il soit vraiment lent avec un seul travailleur.

Un redémarrage du serveur résoudrait le problème, mais je détesterais que la fonctionnalité de mon site dépendra des redémarrages du serveur.

Est-ce un vrai problème qui se passe? Y a-t-il un moyen de l'éviter?

mise à jour: J'apprécierais vraiment un moyen de prendre une cheminée du fil / ouvrier qui est coincé dans une boucle infinie, alors je pouvais l'avoir envoyé envoyé par courrier électronique, alors je serai au courant du problème. (Je ne sais pas comment faire cela car il n'y a pas d'exception étant soulevée.)

Mise à jour aux personnes qui disent des choses à l'effet de "Éviter l'écriture de code qui a des boucles infinies": au cas où il n'était pas évident, je ne passe pas mon temps libre à mettre intentionnellement des boucles infinies dans mon code. Lorsque ces choses se produisent, ce sont des erreurs et des erreurs peuvent être minimisées mais jamais complètement évitées. Je veux savoir que même lorsque je fais une erreur, il y aura un filet de sécurité qui m'informera et me permettra de résoudre le problème.


2 commentaires

lire intéressant: Stackoverflow.com/Questtions/8685695/...


J'ai mis à jour ma réponse, j'espère que ça répond à votre question maintenant :)


3 Réponses :


0
votes

Oui, votre analyse est correcte. Le fil de travail / le processus continuera à courir. De plus, s'il n'y a pas d'attente / sommeil dans la boucle, il aura porté la CPU. D'autres threads / processus obtiendront très peu de processeur, ce qui entraînera votre site complet sur la réponse lente.

En outre, je ne pense pas que le serveur n'enverra aucune erreur de délai d'attente au client explicitement. Si le délai d'attente TCP est défini, la connexion TCP sera fermée.

Le client peut également avoir un délai d'attente pour obtenir une réponse, qui peut entrer en image.

Éviter ce code est le meilleur moyen d'éviter ce code. Vous pouvez également avoir un outil de surveillance sur le serveur pour rechercher une utilisation de la CPU / Memory et de notifier à une activité anormale afin que vous puissiez agir.


0 commentaires

2
votes

Je viens de tester cela sur le serveur de développement de Django.

résultats:

  • ne donne pas de délai d'attente après 30 secondes. (Cela pourrait parce que ce n'est pas un serveur de production cependant)
  • reste en cours de chargement jusqu'à ce que je ferme la page.

    Je suppose une façon de l'éviter, sans simplement éviter un code comme celui-ci, serait d'utiliser le threading pour avoir le contrôle des délais d'attente et d'arrêter le fil.

    peut-être peut-être quelque chose comme: xxx


3 commentaires

En fait, maintenant que je pense, vous pouvez appeler le thread = myTythread () dans une autre fonction afin que vous puissiez y accéder et l'arrêter plus tard. Mais toujours une solution possible?


Je ne comprends vraiment pas comment votre réponse résout quoi que ce soit. Pour une chose, le code doit finir avant la réponse est renvoyée. Deuxièmement, vous n'avez même pas montré comment le fil que vous avez créé sera automatiquement arrêté.


Oh, tu as raison, je suppose que je ne pensais pas ça autant. Je suis désolé.



5
votes

C'est un vrai problème. En cas de gevent, en raison de la commutation de contexte, il peut même arrêter immédiatement votre site Web de répondre.

Tout dépend de votre environnement. Par exemple, lors de l'exécution de Django en production via UWSGI, vous pouvez définir harakiri - c'est l'heure en secondes, après quoi la manipulation du fil de la demande sera tuée si elle n'a pas fini de manipuler la réponse. Il est fortement recommandé de définir une telle valeur afin de traiter certaines demandes défectueuses ou un mauvais code. Cet événement est signalé dans le journal UWSGI. Je crois que d'autres solutions pour la gestion de Django dans la production ont des options similaires.

Sinon, en raison de l'architecture de réseau, la déconnexion du client n'arrête pas la boucle infinie et, par défaut, il n'y aura aucune réponse du tout - juste un chargement infini. Différentes options de délai d'attente (l'une des quelles harakiri est) peut finir par montrer le délai de connexion - par exemple, PHP a (autant que je me souvienne) du délai d'attente par défaut de 30 secondes et il renvoie 504 timets de passerelle. Délai de déconnexion de socket dépend des paramètres de serveur HTTP et n'arrêtera pas le thread d'applications, il ne fermera que la prise du client.

Si vous n'utilisez pas GEVENT (ou d'autres threads verts), une boucle infinie aura tendance à prendre 100% de la puissance CPU disponible (limitée à un noyau), éventuellement manger de plus en plus de mémoire, votre site Web fonctionnera donc assez lentement. et / ou timeout vraiment rapide. Django elle-même n'est pas au courant de la demande, de sorte que, comme mentionné précédemment, votre pile d'environnement de production est le moyen de l'empêcher de se produire. Dans le cas d'UWSGI, http: //uwsgi-docs.readthedocs. org / fr / Dernières options.html # Harakiri-Verbose est la voie à suivre.

Harakiri imprime la trace de la pile des processus tués: ( https : //uwsgidiocs.readthedocs.org/fr/latest/traceBacker.html? Highlight = Harakiri ) directement au journal UWSGI, et en raison du système d'alarme, vous pouvez être notifié via e-mail ( http://uwsgi-docs.readthedocs.org/en/latest/alarmsubsystem.html )


2 commentaires

L'option Harakiri est une étape dans la bonne direction, car elle empêche le serveur d'être bloqué, mais cela ne vous aide pas à trouver la racine du problème et à le réparer. Ce que je voudrais, c'est d'avoir une stacktrace du travailleur offensant envoyé par courrier électronique afin que je puisse inspecter et résoudre le problème dans le code.


Harakiri imprime des informations sur la trace de la pile et les demandes de la pile, et Nginx Alarm System permet la notification par courrier électronique. Réponse mise à jour avec des liens.