Gunicorn: Délais d'expiration instantanés des nœuds de calcul après des requêtes de longue durée

Créé le 8 août 2013  ·  45Commentaires  ·  Source: benoitc/gunicorn

Nous avons rencontré un problème très étrange impliquant des délais d'attente de demande avec Gunicorn s'exécutant devant notre application Django sur Heroku.

Essentiellement, le problème se produit lorsqu'une demande de très longue durée est adressée à l'application, ce qui entraîne son interruption par le délai d'expiration de la demande au niveau de la

[CRITICAL] WORKER TIMEOUT (pid:15)

Il en résulte qu'une page d'erreur interne du serveur est immédiatement renvoyée au client. Ce comportement n'est pas cohérent - parfois la prochaine requête réussira, parfois non. Je soupçonne que l'erreur se produira si la demande est traitée par le même travailleur Gunicorn qui s'occupait de la demande de longue durée.

Nous exécutons Gunicorn directement depuis Django comme suit :

python app/manage.py run_gunicorn -b 0.0.0.0:$PORT -w 2 -k gevent

D'autres paramètres de configuration pertinents, tels que worker_connections et max_requests, sont définis sur leurs valeurs par défaut. Cependant, nous avons expérimenté la modification de ces paramètres, ainsi que le nombre de travailleurs, mais le problème décrit ci-dessus se produit dans tous les cas que nous avons essayés. Notre version actuelle de Gunicorn est 0.14.6, ayant été annulée après la mise à niveau vers 17.5 au cas où cela serait la source du problème. Malheureusement, le même comportement se produit sur les deux versions.

Nous avons beaucoup de mal à comprendre l'origine de ce problème. À partir de la documentation Heroku liée ci-dessus :

Tant que le routeur a renvoyé une réponse au client, votre application ne saura pas que la demande qu'elle traite a atteint un délai d'attente et votre application continuera à travailler sur la demande.

Je suppose que cela signifie que malgré le fait que la demande initiale de longue durée ait expiré du point de vue du client, un travailleur de Gunicorn traite toujours la demande. Ce qui me déconcerte, c'est comment cela entraînerait une nouvelle demande ultérieure pour lancer immédiatement un délai de travail, étant donné que les travailleurs utilisent gevent et donc des threads asynchrones pour gérer les demandes. J'aurais pensé que la première demande de longue date serait

  1. non bloquant en raison du fait qu'il existe plusieurs threads de travail gevent, et
  2. tué par Gunicorn avant que toute demande ultérieure ne se produise, car le délai d'expiration de la demande par défaut pour Gunicorn est de 30 secondes - identique au délai d'expiration de la demande d'Heroku.

Il peut être intéressant de mentionner que les requêtes de longue durée se connectent à notre base de données PostgreSQL et effectuent plusieurs requêtes complexes. Les plantages ne semblent se produire qu'après l'expiration de la connexion de longue durée grâce à Heroku lors de l'interfaçage avec la base de données. Nous avons testé cela sur notre serveur de test en créant deux vues distinctes, dont l'une exécute de longues requêtes sur la base de données jusqu'à ce qu'un délai d'expiration Heroku soit atteint, et l'autre attend simplement au-delà de la barre des 30 secondes pour produire le délai d'expiration Heroku. L'ancienne vue était capable de provoquer des délais d'attente des travailleurs Gunicorn lors de la demande suivante, alors que la vue "en veille" n'était pas .

Ce serait fantastique si quelqu'un avait une idée du comportement sous-jacent à l'origine de ce problème - toute information supplémentaire que je peux fournir pour aider à diagnostiquer le problème, veuillez me le faire savoir. J'espère que c'est la bonne façon de traiter un tel problème et qu'il n'a pas été soulevé/résolu auparavant.

( FeaturWorker - Bugs -

Tous les 45 commentaires

@Jwpe Excellent rapport de bogue.

La première chose que j'examinerais est de savoir si vous utilisez un pilote PostgreSQL écologique. Il y avait une version spécifique que vous deviez utiliser avec un patch singe pour que cela fonctionne correctement. Je ne connais pas l'état actuel des choses maintenant. Mais le délai d'expiration que vous avez collé est un délai d'expiration de travailleur et dans l'un des travailleurs asynchrones, cela se résume essentiellement à "un greenlet n'a pas cédé pendant plus de $ timeout secondes". Étant donné que vous décrivez des requêtes PostgreSQL de longue durée, c'est le premier endroit où j'enquêterais.

@davisp Merci pour la réponse rapide à ce sujet !

En suivant votre pointeur, j'ai jeté un coup d'œil à l'adaptateur psycopg2 - que nous utilisons pour connecter notre application Django à Postgres - et j'ai découvert cette section de la documentation qui indique :

Avertissement : Les connexions Psycopg ne sont pas sécurisées pour les threads verts et ne peuvent pas être utilisées simultanément par différents threads verts. Essayer d'exécuter plus d'une commande à la fois en utilisant un curseur par thread entraînera une erreur (ou un blocage sur les versions antérieures à 2.4.2).
Par conséquent, il est conseillé aux programmeurs d'éviter de partager les connexions entre les coroutines ou d'utiliser un verrou compatible avec les bibliothèques pour synchroniser les connexions partagées, par exemple pour la mise en commun.

En d'autres termes, psycopg2 n'aime pas les fils verts. Sur la base du comportement que nous avons rencontré, je suppose que c'est la source de l'erreur. La manière suggérée de traiter ce problème, selon la documentation de psycopg, consiste à utiliser une bibliothèque qui permet la prise en charge de psycopg pour les coroutines. La bibliothèque recommandée est psycogreen .

Je vais essayer de recréer le problème sur notre serveur de test à l'aide de la bibliothèque psycogreen et voir si cela résout le problème. J'espère que je devrais être en mesure de rapporter des résultats assez rapidement.

@Jwpe Cela ressemble au crochet dont je me souvenais.

@benoitc Peut-être

@davisp peut-être dans une section FAQ ?

hmppff a oublié qu'il existait déjà (http://docs.gunicorn.org/en/latest/faq.html) Donc peut-être pourrions-nous avoir un lien vers une section "dépannage" à partir de là. pas sûr, mais nous pourrions également déplacer dans cette section des informations sur virtualenv et d'autres astuces.

Peut-être une page de mises en garde ou de « Notes sur les fils verts ». Pas super pressant.

Je voyais pratiquement le même comportement exact sur Heroku exécutant gunicorn avec des travailleurs gevent et quelques autres, alors je suis passé aux travailleurs synchrones, comme recommandé sur ce fil et je voyais toujours le même problème grave. J'obtiendrais une coupure Heroku de 30 secondes H12, puis je répéterais les erreurs H12 et [CRITICAL] Worker Timeout jusqu'à ce que je réinitialise tout le dyno (parfois une heure ou plus plus tard ou jusqu'à ce que les demandes maximales soient atteintes). J'ai donc ajusté le délai d'expiration du gunicorn à 28 secondes afin qu'il expire avant qu'Heroku ne l'interrompe. Le même problème (ou très similaire) se produit une ou deux fois par jour et persiste jusqu'au redémarrage du processus maître, mais cette fois, il commence par un H13 (connexion fermée) car gunicorn le coupe. Il n'y a pas de pic de trafic significatif pendant ces périodes.

Voici mon entrée de procfile actuelle :

web: newrelic-admin run-program gunicorn publisher.wsgi -b 0.0.0.0:$PORT -w 4 --max-requests 1000 --timeout 28 --preload

Détail de la série d'événements :

Tout d'abord, je reçois quelques requêtes qui semblent prendre très longtemps (5 secondes et plus), puis une requête échoue avec un délai d'attente H12 (le délai d'attente du travailleur l'interrompt) et quelques autres requêtes se termineront, mais avec des délais exceptionnellement longs (20 secondes). À partir de là, il s'agit d'une coupure heroku pure de 30 secondes H11 jusqu'à ce que je redémarre le dyno.

Nous utilisons gunicorn (v 18.0) comme serveur Web (qui exécute python/django).

Nous exécutons newrelic, qui montre les temps d'arrêt et les temps de file d'attente des demandes incroyablement élevés, mais n'offre aucun autre aperçu. Il n'y avait pas de pics de débit ou d'autres conditions anormales que je peux voir dans NR. Nous utilisons papertrail pour le traitement des journaux et pour envoyer des e-mails d'erreur.

Oct 15 15:08:53 nutrislice-stockton heroku/router: at=info method=GET path=/marketingtools/api/slides/?format=json-p&callback=_jqjsp&_1381871332239= host=oldham.nutrislice.com fwd="74.138.24.95" dyno=web.2 connect=15ms service=216ms status=200 bytes=21 Oct 15 15:08:54 nutrislice-stockton heroku/router: at=info method=GET path=/menu/api/menutypes/?format=json-p&callback=_jqjsp&_1381871332232= host=oldham.nutrislice.com fwd="74.138.24.95" dyno=web.2 connect=2ms service=90ms status=200 bytes=231 Oct 15 15:08:56 nutrislice-stockton heroku/router: at=info method=GET path=/menu/api/schools/?format=json-p&callback=_jqjsp&_1381871323514= host=oldham.nutrislice.com fwd="74.138.24.95" dyno=web.2 connect=3ms service=94ms status=200 bytes=5986 Oct 15 15:09:03 nutrislice-stockton heroku/router: at=info method=HEAD path=/heartbeat/ host=stockton.nutrislice.com fwd="54.247.188.179" dyno=web.2 connect=3ms service=23ms status=200 bytes=0 Oct 15 15:09:13 nutrislice-stockton heroku/router: at=info method=GET path=/menu/api/settings/?format=json-p&callback=_jqjsp&_1381871237946= host=pcsb.nutrislice.com fwd="66.87.110.127" dyno=web.2 connect=5ms service=166ms status=200 bytes=468 Oct 15 15:09:20 nutrislice-stockton heroku/router: at=info method=GET path=/menu/api/settings/?format=json-p&callback=_jqjsp&_1381871323611= host=oldham.nutrislice.com fwd="74.138.24.95" dyno=web.2 connect=6ms service=183ms status=200 bytes=453 Oct 15 15:09:40 nutrislice-stockton heroku/router: at=info method=GET path=/ host=nps.nutrislice.com fwd="74.190.240.28" dyno=web.2 connect=1ms service=260ms status=200 bytes=35951 Oct 15 15:09:55 nutrislice-stockton heroku/router: at=info method=GET path=/menuwidgets/api/list/school-menu-profile/87/menu-type/43/?format=json-p&callback=jQuery18008709754704032093_1381871379465&_=1381871393589 host=nps.nutrislice.com fwd="74.190.240.28" dyno=web.2 connect=15ms service=129ms status=200 bytes=400 Oct 15 15:09:55 nutrislice-stockton heroku/router: at=info method=GET path=/menuwidgets/api/list/school-menu-profile/306/menu-type/187/?format=json-p&callback=jQuery180013075259909965098_1381873891397&_=1381873896600 host=sdhc.nutrislice.com fwd="72.186.96.121" dyno=web.2 connect=2ms service=33ms status=200 bytes=486 Oct 15 15:10:00 nutrislice-stockton heroku/router: at=info method=GET path=/menuwidgets/186/?smp=257 host=coppellisd.nutrislice.com fwd="76.199.114.157" dyno=web.2 connect=7ms service=103ms status=200 bytes=323 Oct 15 15:10:00 nutrislice-stockton app/web.2: INFO http://stockton.nutrislice.com/heartbeat/ Pinged from IP: 10.190.159.205 -- AGENT: NewRelicPinger/1.0 (269661) Oct 15 15:10:00 nutrislice-stockton heroku/router: at=info method=HEAD path=/heartbeat/ host=stockton.nutrislice.com fwd="50.112.95.211" dyno=web.2 connect=1ms service=10ms status=200 bytes=0 Oct 15 15:10:09 nutrislice-stockton heroku/router: at=info method=GET path=/menuwidgets/239/?smp=341 host=edenpr.nutrislice.com fwd="75.73.177.139" dyno=web.2 connect=8ms service=334ms status=200 bytes=277 Oct 15 15:10:16 nutrislice-stockton heroku/router: at=info method=GET path=/menuwidgets/395/?smp=306 host=sdhc.nutrislice.com fwd="72.186.96.121" dyno=web.2 connect=1ms service=96ms status=200 bytes=245 Oct 15 15:10:20 nutrislice-stockton heroku/router: at=info method=GET path=/menuwidgets/391/?smp=305 host=sdhc.nutrislice.com fwd="173.170.34.126" dyno=web.2 connect=32ms service=5207ms status=200 bytes=290 Oct 15 15:10:22 nutrislice-stockton heroku/router: at=info method=GET path=/menuwidgets/350/?smp=305 host=sdhc.nutrislice.com fwd="173.170.34.126" dyno=web.2 connect=60ms service=7676ms status=200 bytes=1147 Oct 15 15:10:31 nutrislice-stockton heroku/router: at=info method=GET path=/menuwidgets/258/?smp=341 host=edenpr.nutrislice.com fwd="75.73.177.139" dyno=web.2 connect=42ms service=517ms status=200 bytes=26974 Oct 15 15:10:43 nutrislice-stockton heroku/router: at=info method=GET path=/menu/api/schools/?format=json-p&callback=_jqjsp&_1381871432885= host=ocps.nutrislice.com fwd="71.47.21.97" dyno=web.2 connect=1490ms service=9883ms status=200 bytes=1565 Oct 15 15:10:52 nutrislice-stockton heroku/router: at=error code=H13 desc="Connection closed without response" method=GET path=/ host=jordandistrict.nutrislice.com fwd="71.199.48.37" dyno=web.2 connect=1959ms service=29230ms status=503 bytes=0 Oct 15 15:10:52 nutrislice-stockton app/web.2: 2013-10-15 21:10:50 [2] [CRITICAL] WORKER TIMEOUT (pid:12) Oct 15 15:10:52 nutrislice-stockton app/web.2: 2013-10-15 21:10:50 [2] [CRITICAL] WORKER TIMEOUT (pid:12) Oct 15 15:10:52 nutrislice-stockton app/web.2: 2013-10-15 21:10:50 [26] [INFO] Booting worker with pid: 26 Oct 15 15:10:52 nutrislice-stockton app/web.2: 2013-10-15 21:10:50,930 (26/MainThread) newrelic.core.agent INFO - New Relic Python Agent (2.0.0.1) Oct 15 15:10:54 nutrislice-stockton heroku/router: at=info method=GET path=/surveys/api/activesurveycount/?format=json-p&callback=_jqjsp&_1381871433429= host=henrico.nutrislice.com fwd="96.248.5.53" dyno=web.2 connect=1181ms service=20074ms status=200 bytes=32 Oct 15 15:10:55 nutrislice-stockton heroku/router: at=info method=GET path=/menu/api/schooltypes/?format=json-p&callback=_jqjsp&_1381871433374= host=henrico.nutrislice.com fwd="96.248.5.53" dyno=web.2 connect=1136ms service=20393ms status=200 bytes=142 Oct 15 15:11:01 nutrislice-stockton app/web.2: using heroku production settings Oct 15 15:11:01 nutrislice-stockton app/web.2: WARNING /app/.heroku/python/lib/python2.7/site-packages/django/utils/hashcompat.py:9: DeprecationWarning: django.utils.hashcompat is deprecated; use hashlib instead Oct 15 15:11:01 nutrislice-stockton app/web.2: DeprecationWarning) Oct 15 15:11:01 nutrislice-stockton heroku/router: at=info method=GET path=/menu/api/settings/?format=json-p&callback=_jqjsp&_1381871432922= host=ocps.nutrislice.com fwd="71.47.21.97" dyno=web.2 connect=1435ms service=23198ms status=200 bytes=486 Oct 15 15:11:03 nutrislice-stockton app/web.2: WARNING /app/.heroku/python/lib/python2.7/site-packages/django/conf/urls/defaults.py:3: DeprecationWarning: django.conf.urls.defaults is deprecated; use django.conf.urls instead Oct 15 15:11:03 nutrislice-stockton app/web.2: DeprecationWarning) Oct 15 15:11:05 nutrislice-stockton heroku/router: at=info method=GET path=/menu/api/schooltypes/?format=json-p&callback=_jqjsp&_1381871443300= host=martinschools.nutrislice.com fwd="99.114.229.202" dyno=web.2 connect=1089ms service=20040ms status=200 bytes=268 Oct 15 15:11:10 nutrislice-stockton heroku/router: at=error code=H12 desc="Request timeout" method=GET path=/menu/api/weeks/school-menu-profile/135/menu-type/63/2013/10/14/?format=json-p&callback=_jqjsp&_1381871439548= host=henrico.nutrislice.com fwd="96.248.5.53" dyno=web.2 connect=1018ms service=30001ms status=503 bytes=0 Oct 15 15:11:15 nutrislice-stockton heroku/router: at=error code=H12 desc="Request timeout" method=GET path=/menu/api/sales/?format=json-p&callback=_jqjsp&_1381871443267= host=martinschools.nutrislice.com fwd="99.114.229.202" dyno=web.2 connect=1096ms service=30001ms status=503 bytes=0 Oct 15 15:11:15 nutrislice-stockton heroku/router: at=error code=H12 desc="Request timeout" method=GET path=/menu/api/schools/?format=json-p&callback=_jqjsp&_1381871443296= host=martinschools.nutrislice.com fwd="99.114.229.202" dyno=web.2 connect=1108ms service=30000ms status=503 bytes=0 Oct 15 15:11:23 nutrislice-stockton heroku/router: at=info method=GET path=/menu/api/weeks/school-menu-profile/48/menu-type/21/2013/10/14/?format=json-p&callback=_jqjsp&_1381871449451= host=martinschools.nutrislice.com fwd="99.114.229.202" dyno=web.2 connect=1114ms service=31756ms status=200 bytes=48771 Oct 15 15:11:26 nutrislice-stockton heroku/router: at=error code=H12 desc="Request timeout" method=GET path=/menu/api/sales/?format=json-p&callback=_jqjsp&_1381871455129= host=pcsb.nutrislice.com fwd="66.87.110.127" dyno=web.2 connect=990ms service=30001ms status=503 bytes=0 Oct 15 15:11:26 nutrislice-stockton heroku/router: at=error code=H12 desc="Request timeout" method=GET path=/menu/api/schools/?format=json-p&callback=_jqjsp&_1381871455291= host=pcsb.nutrislice.com fwd="66.87.110.127" dyno=web.2 connect=1028ms service=30008ms status=503 bytes=0 Oct 15 15:11:31 nutrislice-stockton heroku/router: at=error code=H12 desc="Request timeout" method=GET path=/menuwidgets/179/?smp=6 host=cusdnutrition.nutrislice.com fwd="68.99.246.16" dyno=web.2 connect=2492ms service=30000ms status=503 bytes=0 Oct 15 15:11:32 nutrislice-stockton heroku/router: at=error code=H12 desc="Request timeout" method=GET path=/menuwidgets/192/?smp=6 host=cusdnutrition.nutrislice.com fwd="68.99.246.16" dyno=web.2 connect=2713ms service=30003ms status=503 bytes=0 Oct 15 15:11:39 nutrislice-stockton heroku/router: at=error code=H12 desc="Request timeout" method=GET path=/menu/ host=hebisd.nutrislice.com fwd="38.107.226.1" dyno=web.2 connect=2115ms service=30001ms status=503 bytes=0 Oct 15 15:11:45 nutrislice-stockton heroku/router: at=error code=H12 desc="Request timeout" method=GET path=/menu/api/weeks/school-menu-profile/44/menu-type/19/2013/10/14/?format=json-p&callback=_jqjsp&_1381871472583= host=pcsb.nutrislice.com fwd="66.87.110.127" dyno=web.2 connect=2168ms service=30000ms status=503 bytes=0 Oct 15 15:11:48 nutrislice-stockton heroku/router: at=error code=H12 desc="Request timeout" method=GET path=/marketingtools/api/active-announcements/?format=json-p&callback=_jqjsp&_1381871476287= host=sdhc.nutrislice.com fwd="65.34.72.116" dyno=web.2 connect=1927ms service=30000ms status=503 bytes=0 Oct 15 15:11:48 nutrislice-stockton heroku/router: at=error code=H12 desc="Request timeout" method=GET path=/surveys/api/activesurveycount/?format=json-p&callback=_jqjsp&_1381871476543= host=sdhc.nutrislice.com fwd="65.34.72.116" dyno=web.2 connect=2117ms service=30000ms status=503 bytes=0 Oct 15 15:11:48 nutrislice-stockton heroku/router: at=error code=H12 desc="Request timeout" method=GET path=/menu/api/schooltypes/?format=json-p&callback=_jqjsp&_1381871476481= host=sdhc.nutrislice.com fwd="65.34.72.116" dyno=web.2 connect=2111ms service=30009ms status=503 bytes=0 Oct 15 15:11:50 nutrislice-stockton app/web.2: 2013-10-15 15:11:32,597 (26/NR-Activate-Session/nutrislice-stockton) newrelic.core.data_collector INFO - Successfully registered New Relic Python agent where app_name='nutrislice-stockton', pid=26, redirect_host='collector-2.newrelic.com' and agent_run_id=474482914, in 40.26 seconds. Oct 15 15:11:50 nutrislice-stockton app/web.2: INFO Successfully registered New Relic Python agent where app_name='nutrislice-stockton', pid=26, redirect_host='collector-2.newrelic.com' and agent_run_id=474482914, in 40.26 seconds. Oct 15 15:11:52 nutrislice-stockton heroku/router: at=error code=H12 desc="Request timeout" method=GET path=/marketingtools/api/active-announcements/?format=json-p&callback=_jqjsp&_1381871480294= host=sdhc.nutrislice.com fwd="65.34.72.116" dyno=web.2 connect=1689ms service=30006ms status=503 bytes=0 Oct 15 15:11:55 nutrislice-stockton heroku/router: at=error code=H12 desc="Request timeout" method=GET path=/menu/api/settings/?format=json-p&callback=_jqjsp&_1381871482566= host=henrico.nutrislice.com fwd="72.84.233.45" dyno=web.2 connect=2067ms service=30004ms status=503 bytes=0 Oct 15 15:11:57 nutrislice-stockton app/web.2: 2013-10-15 21:11:41 [2] [CRITICAL] WORKER TIMEOUT (pid:26) Oct 15 15:11:57 nutrislice-stockton app/web.2: 2013-10-15 21:11:41 [2] [CRITICAL] WORKER TIMEOUT (pid:26) Oct 15 15:11:57 nutrislice-stockton app/web.2: 2013-10-15 21:11:41 [29] [INFO] Booting worker with pid: 29 Oct 15 15:11:57 nutrislice-stockton app/web.2: 2013-10-15 21:11:41,067 (29/MainThread) newrelic.core.agent INFO - New Relic Python Agent (2.0.0.1) Oct 15 15:11:57 nutrislice-stockton app/web.2: using heroku production settings Oct 15 15:11:57 nutrislice-stockton app/web.2: WARNING /app/.heroku/python/lib/python2.7/site-packages/django/utils/hashcompat.py:9: DeprecationWarning: django.utils.hashcompat is deprecated; use hashlib instead Oct 15 15:11:57 nutrislice-stockton app/web.2: DeprecationWarning) Oct 15 15:11:57 nutrislice-stockton app/web.2: 2013-10-15 21:11:44 [2] [CRITICAL] WORKER TIMEOUT (pid:23) Oct 15 15:11:57 nutrislice-stockton app/web.2: 2013-10-15 21:11:44 [2] [CRITICAL] WORKER TIMEOUT (pid:23) Oct 15 15:11:57 nutrislice-stockton app/web.2: 2013-10-15 21:11:44 [32] [INFO] Booting worker with pid: 32 Oct 15 15:11:57 nutrislice-stockton app/web.2: 2013-10-15 21:11:44,154 (32/MainThread) newrelic.core.agent INFO - New Relic Python Agent (2.0.0.1) Oct 15 15:11:57 nutrislice-stockton app/web.2: using heroku production settings Oct 15 15:11:57 nutrislice-stockton app/web.2: WARNING /app/.heroku/python/lib/python2.7/site-packages/django/utils/hashcompat.py:9: DeprecationWarning: django.utils.hashcompat is deprecated; use hashlib instead Oct 15 15:11:57 nutrislice-stockton app/web.2: DeprecationWarning) Oct 15 15:11:57 nutrislice-stockton app/web.2: 2013-10-15 21:11:48 [2] [CRITICAL] WORKER TIMEOUT (pid:14) Oct 15 15:11:57 nutrislice-stockton app/web.2: 2013-10-15 21:11:48 [2] [CRITICAL] WORKER TIMEOUT (pid:14) Oct 15 15:11:57 nutrislice-stockton app/web.2: 2013-10-15 21:11:48 [35] [INFO] Booting worker with pid: 35 Oct 15 15:11:57 nutrislice-stockton app/web.2: 2013-10-15 21:11:48,273 (35/MainThread) newrelic.core.agent INFO - New Relic Python Agent (2.0.0.1) Oct 15 15:11:57 nutrislice-stockton app/web.2: using heroku production settings Oct 15 15:11:57 nutrislice-stockton app/web.2: WARNING /app/.heroku/python/lib/python2.7/site-packages/django/utils/hashcompat.py:9: DeprecationWarning: django.utils.hashcompat is deprecated; use hashlib instead Oct 15 15:11:57 nutrislice-stockton app/web.2: DeprecationWarning) Oct 15 15:11:57 nutrislice-stockton heroku/router: at=info method=GET path=/menuwidgets/353/?smp=306 host=sdhc.nutrislice.com fwd="72.186.96.121" dyno=web.2 connect=21ms service=76ms status=200 bytes=255 Oct 15 15:12:00 nutrislice-stockton app/web.2: 2013-10-15 21:11:54 [2] [CRITICAL] WORKER TIMEOUT (pid:13) Oct 15 15:12:00 nutrislice-stockton app/web.2: 2013-10-15 21:11:54 [2] [CRITICAL] WORKER TIMEOUT (pid:13) Oct 15 15:12:00 nutrislice-stockton app/web.2: 2013-10-15 21:11:54 [38] [INFO] Booting worker with pid: 38 Oct 15 15:12:00 nutrislice-stockton app/web.2: 2013-10-15 21:11:54,388 (38/MainThread) newrelic.core.agent INFO - New Relic Python Agent (2.0.0.1) Oct 15 15:12:00 nutrislice-stockton app/web.2: using heroku production settings Oct 15 15:12:01 nutrislice-stockton app/web.2: WARNING /app/.heroku/python/lib/python2.7/site-packages/django/utils/hashcompat.py:9: DeprecationWarning: django.utils.hashcompat is deprecated; use hashlib instead Oct 15 15:12:01 nutrislice-stockton app/web.2: DeprecationWarning) Oct 15 15:12:02 nutrislice-stockton app/web.2: WARNING /app/.heroku/python/lib/python2.7/site-packages/django/conf/urls/defaults.py:3: DeprecationWarning: django.conf.urls.defaults is deprecated; use django.conf.urls instead Oct 15 15:12:02 nutrislice-stockton app/web.2: DeprecationWarning) Oct 15 15:12:03 nutrislice-stockton heroku/router: at=error code=H12 desc="Request timeout" method=GET path=/menuwidgets/353/?smp=306 host=sdhc.nutrislice.com fwd="108.9.154.78" dyno=web.2 connect=3650ms service=30006ms status=503 bytes=0 Oct 15 15:12:03 nutrislice-stockton heroku/router: at=error code=H12 desc="Request timeout" method=GET path=/menuwidgets/395/?smp=306 host=sdhc.nutrislice.com fwd="108.9.154.78" dyno=web.2 connect=3581ms service=30006ms status=503 bytes=0 Oct 15 15:12:06 nutrislice-stockton heroku/router: at=error code=H12 desc="Request timeout" method=GET path=/menu/api/settings/?format=json-p&callback=_jqjsp&_1381871492466= host=canyonsdistrict.nutrislice.com fwd="174.52.155.49" dyno=web.2 connect=3582ms service=30001ms status=503 bytes=0 Oct 15 15:12:09 nutrislice-stockton heroku/router: at=error code=H12 desc="Request timeout" method=GET path=/mobile/api_version/?deviceType=iphone host=pasco.nutrislice.com fwd="173.65.148.9" dyno=web.2 connect=3837ms service=30004ms status=503 bytes=0 Oct 15 15:12:11 nutrislice-stockton heroku/router: at=error code=H12 desc="Request timeout" method=GET path=/mobile/api_version/?deviceType=iphone host=canyonsdistrict.nutrislice.com fwd="174.52.155.49" dyno=web.2 connect=3987ms service=30001ms status=503 bytes=0 Oct 15 15:12:11 nutrislice-stockton heroku/router: at=error code=H12 desc="Request timeout" method=GET path=/menu/api/schools/?format=json-p&callback=_jqjsp&_1381871497105= host=canyonsdistrict.nutrislice.com fwd="174.52.155.49" dyno=web.2 connect=3962ms service=30001ms status=503 bytes=0 Oct 15 15:12:11 nutrislice-stockton heroku/router: at=error code=H12 desc="Request timeout" method=GET path=/menu/api/menutypes/?format=json-p&callback=_jqjsp&_1381871497128= host=canyonsdistrict.nutrislice.com fwd="174.52.155.49" dyno=web.2 connect=4020ms service=30007ms status=503 bytes=0
Et cette « spirale de la mort » des temporisations H12 et des TEMPS MORT [CRITIQUE] DES TRAVAILLEURS se poursuit indéfiniment jusqu'à ce que le processus maître soit redémarré.

Des idées si c'est le même problème ou un autre? Des suggestions pour corriger? Je pense que puisque gunicorn tue les processus de travail après leur expiration et les redémarre, ils pourraient commencer à traiter les choses normalement, mais il semble que les demandes ne leur parviennent même pas après cela. C'est peut-être un problème Heroku.

:+1: Voir aussi ce problème.

Je vois aussi ce problème sur Heroku

@sprynmr @richardkeen pouvez-vous partager la façon dont vous lancez gunicorn et n'importe quel journal que vous pouvez? Cela aiderait beaucoup à résoudre le problème.

@nebstrebor et si vous ne

Nous l'avons lancé comme ceci :
web: newrelic-admin run-program python manage.py run_gunicorn -b "0.0.0.0:$PORT" --log-level=DEBUG -w 3 -k gevent --max-requests 250

Même avec le DEBUG au niveau du journal, nous n'avons pas eu beaucoup de journaux sur ce qui se passait. Ne pas utiliser gevent a résolu le problème pour nous pour le moment, mais ce n'est pas idéal.

@sprynmr et si vous supprimiez le nombre maximum de requêtes ? Aussi quelle version de gevent?

Nous étions sur 1.0rc2 . Pas sûr du nombre maximum de demandes. Je ne veux pas vraiment le réactiver pour notre environnement de production pour le moment.

En lisant la page Heroku sur le délai d'expiration de la well under 30 seconds, such as 10 or 15 l'application

Quoi qu'il en soit, le problème apparaissant avec gevent est probablement dû à la façon dont les connexions sont gérées. La version actuelle du worker génère un greenlet / connexions acceptées sans réelle supervision de ce greenlet. Ce qui se passe probablement, c'est que l'un des sockets acceptés attendra longtemps et qu'aucun autre événement n'est géré, ce qui fait redémarrer le travailleur gunicorn. Mais je dois vérifier..

Intéressant. Non, nous n'avons pas essayé.

:+1: Je le vois aussi sur mon application. @Jwpe / @sprynmr avez-vous déjà

Merci!

@dencold avez-vous essayé https://github.com/benoitc/gunicorn/issues/588#issuecomment -29267541

Je n'ai pas de compte chez heroku donc je ne sais pas ce qu'il fait. Avez-vous également les mêmes logs ?

Salut @benoitc , merci beaucoup pour la réponse rapide. Les journaux sont exactement les mêmes que ceux rapportés par @Jwpe et @nebstrebor . Je suis heureux de retirer les éléments pertinents et de les ajouter ici si cela peut aider à isoler le problème, faites-le moi savoir.

Je vais suivre vos conseils dans votre commentaire précédent et configurer le délai d'expiration de gunicorn pour qu'il soit inférieur au délai d'expiration du routeur heroku et voir si cela aide. Merci pour la suggestion.

Il serait utile de connaître la cause réelle de cette défaillance en cascade. Il est vraiment étrange de voir un ouvrier échouer et puis tout le serveur gunicorn devient complètement insensible. Faites-moi savoir s'il y a quelque chose que je peux faire pour aider à diagnostiquer. Je ne suis pas en mesure de reproduire ce délai d'attente localement. Il semble ne se produire que sur l'infrastructure heroku.

Désolé @dencold, je n'ai jamais trouvé de solution. Cela semblait être un bug mystérieux très profond, et je n'ai pas eu le temps de me battre avec lui. Sera curieux de voir si le bit de délai d'attente vous aide. Rapport.

@dencold utilisez -vous également une nouvelle relique ?

@benoitc oui , nous utilisons également une nouvelle relique.

@dencold de même, nous n'avons jamais résolu ce problème avec succès. Nous n'avions pas le temps d'investir pour déterminer la cause des erreurs et nous devions nous concentrer sur la réduction de la durée des requêtes initiales. Cependant, la nature critique de l'erreur - puisqu'elle était destinée à l'utilisateur - nous a amenés à changer de serveur WSGI pour éviter le problème dans l'intervalle. Par conséquent, nous n'avons pas effectué d'autres expériences pour catégoriser davantage le problème.

@Jwpe avez-vous au moins essayé la solution proposée ? De plus, le résultat est bizarre et je ne reproduis jamais ça avec le gunicorn tout seul.

J'avais le temps de coupure à 15 secondes et je voyais toujours le problème

Le dimanche 26 janvier 2014, Benoit Chesneau [email protected]
a écrit:

@Jwpe https://github.com/Jwpe avez-vous au moins essayé la proposition
Solution? De plus le résultat est bizarre et je ne reproduis jamais ça avec gunicorn
par lui-même.

-
Répondez directement à cet e-mail ou consultez-le sur Gi tHubhttps://github.com/benoitc/gunicorn/issues/588#issuecomment -33316333
.

Ben Roberts
Directeur technique
Nutrislice, Inc.
866-524-3444 poste 702
[email protected]

@Jwpe / @nebstrebor merci beaucoup pour votre retour sur ce problème.

@benoitc, nous avons implémenté la solution de délai d'attente proposée sur notre instance heroku. Je vais surveiller cela de près dans les jours à venir. Je posterai si je vois le même problème apparaître après la mise en place du nouveau délai d'attente.

Merci encore à tous pour l'aide. Bon à savoir que je ne suis pas le seul à rencontrer ce problème. J'espère que nous pourrons aller au fond de la cause.

@benoitc voulait juste signaler que cela faisait environ deux semaines avec le délai d'attente inférieur en place. Nous avons vu quelques délais d'attente des travailleurs, mais aucun ne fait que l'ensemble du processus gunicorn ne répond plus. Cela semble résoudre le problème, mais je ne sais toujours pas pourquoi les délais d'attente de 30 secondes étaient à l'origine de l'erreur en cascade.

Je voulais juste vous tenir au courant. Merci encore pour toute l'aide ici!

Avoir la même erreur [CRITICAL] WORKER TIMEOUT en exécutant Django avec gunicorn dans un Raspberry PI.

Pas de nouvelles.

J'obtiens le même TEMPS MORT [CRITIQUE] POUR LE TRAVAILLEUR.
Le problème est qu'après le délai d'attente réel du travailleur (demande longue), le gunicorn tue le travailleur et essaie d'en générer un nouveau, mais le nouveau travailleur n'a pas pu démarrer dans la limite de TIMEOUT et n'atteint pas l'endroit où il informe le processus parent qu'il est live, donc le gunicorn le tue encore et encore :(. Dans notre cas, le problème était lié à Gevent et Sentry (https://github.com/getsentry/raven-python/issues/305). Sentry se bloque juste au démarrage .
BTW Il sera utile d'avoir un délai d'expiration séparé pour l'heure de début du travailleur et des journaux supplémentaires au sein d'un travailleur qu'il ne peut pas démarrer dans un délai de "délai d'expiration".

Le délai d'attente n'est pas un délai d'attente de demande, sauf sur le travailleur de synchronisation. Les autres travailleurs battent toujours le cœur de l'arbitre, même lorsqu'ils traitent de longues demandes. Le délai d'attente est le délai d'attente de démarrage dans ce cas.

Dans un sens, il n'y a pas de "délai d'attente de demande" dans gunicorn.

oui, le délai d'expiration du travailleur diffère du délai d'expiration de la demande en async. Mais les requêtes de longue durée sans aucun appel de fonction où une "commutation de contexte" asynchrone peut se produire (comme "socket - lecture/écriture") sont les causes des délais d'attente des travailleurs. Et en plus, il peut y avoir un délai d'attente au démarrage du travailleur (où il n'y a aucune demande du tout). Mais dans les journaux Gunicorn, il n'y a aucun moyen de distinguer ces 2 cas différents, il n'y a qu'un seul message "WORKER TIMEOUT".

Devrions-nous ajouter un paramètre de délai d'expiration de la demande ? Cela permettrait aux applications avec de longs démarrages de dépasser le délai d'expiration du travailleur.

Ne le pense pas, à cause de
1) La mesure du temps d'exécution de la demande est difficile, nous ne pouvons pas utiliser la différence de temps au début et à la fin de la demande.
2) Comme je le sais, la capture des délais d'attente des "unités d'exécution" (la quantité de code qui s'exécute entre les changements de contexte) n'est pas possible dans gevent.

Une suggestion alors ?

Si ce problème est dû uniquement à des délais d'attente légitimes et potentiellement en cascade
délais d'attente dus à la charge du serveur qui n'existe pas à la première exécution, y a-t-il
quelque chose à faire ici ? Ou est-ce que ce problème peut être résolu et qu'il est mieux géré
opérationnellement à un autre niveau d'infrastructure ?
Le 30 juillet 2014 à 13h14, "Mkrtich" [email protected] a écrit :

Ne le pense pas, à cause de
1) La mesure du temps d'exécution de la demande est difficile, nous ne pouvons pas utiliser la différence de temps au
mendicité et en fin de demande.
2) Comme je le sais, attraper les délais d'attente des "unités d'exécution" (la quantité de code
qui s'exécute entre le changement de contexte) n'est pas possible dans gevent.

-
Répondez directement à cet e-mail ou consultez-le sur GitHub
https://github.com/benoitc/gunicorn/issues/588#issuecomment -50673040.

La suggestion est d'avoir 2 paramètres de délai d'attente et 2 journaux différents.
1) L'un est le paramètre de délai d'attente actuel qui ne fonctionnera que pendant le traitement de la demande.
2) Le second sera le délai d'expiration du démarrage du travailleur.

Voir aussi ce problème

Nous avons fini par passer à uWSGI pour Heroku et avons eu un meilleur succès ... pas un correctif pour Gunicorn, je me rends compte, mais j'ai pensé que la suggestion pourrait être utile à quelqu'un qui voit ce problème sur son serveur de production et a besoin d'une résolution le plus tôt possible .

@nebstrebor avez-vous bien essayé la suggestion de réduire le délai d'attente ?

@CrazyPython le ticket a été fermé. Pouvez-vous ouvrir un nouveau ticket, décrire le problème que vous rencontrez et comment nous pouvons le reproduire ? Cela aiderait certainement à comprendre s'il s'agit du même problème, autre chose et co :)

Oui, cela n'a pas fait de différence, comme indiqué ci-dessus. Le problème était sporadique
assez (n'a jamais été capable de se reproduire) et assez catastrophique pour que nous devions
faire ce mouvement (ça fait plus d'un an). J'aime vraiment Gunicorn cependant,
et nous l'utilisons en dehors de Heroku sans problème.

Ben Roberts
CTO & Co-fondateur
Nutrislice, Inc.
[email protected]
cellule - 801-735-7845

Le Mar 30 Juin 2015 à 08:08, Benoit Chesneau [email protected]
a écrit:

@nebstrebor https://github.com/nebstrebor bien avez-vous essayé le
suggestion pour réduire le délai d'attente ?

@CrazyPython https://github.com/CrazyPython le ticket a été fermé.
Pouvez-vous ouvrir un nouveau ticket décrire le problème que vous rencontrez et comment nous pouvons
le reproduire ? Il serait certainement utile de savoir si c'est le même problème,
autre chose et co :)

-
Répondez directement à cet e-mail ou consultez-le sur GitHub
https://github.com/benoitc/gunicorn/issues/588#issuecomment-117199606 .

Je pense que nous voyons ce problème aussi. Les deux travailleurs (--workers 2) ont été bloqués par des requêtes de longue durée, ont finalement été tués (--timeout 20), et nous voyons immédiatement deux H13, puis nous commençons à obtenir des redémarrages H12 et WORKER TIMEOUT. Au cours des 10 minutes suivantes, cela a continué, les travailleurs n'ont jamais traité avec succès une demande avant d'atteindre le délai d'expiration et de redémarrer. Nous avons donc redémarré le dyno et cela a résolu le problème.

Une chose intéressante que j'ai remarquée et que je n'ai vu personne d'autre noter - nous voyons deux H13 (Connexion fermée sans réponse) au début du problème, puis lorsque nous avons finalement émis le SIGTERM, nous avons vu un flot de H13 - 48 pour être exact, c'est le même nombre de TEMPS D'ATTENTE DU TRAVAILLEUR que nous avons vus (à l'exception des deux premiers pour lesquels nous avons vu un H13 immédiat). Je ne sais pas exactement ce que cela signifie, mais cela semble suspect...

qu'est-ce que le H13 ou le H12 ? Est-ce quelque chose d'heroku ? Comment est donné le port sur lequel gunicorn sera lié ? Je soupçonne que le proxy heroku ne détecte pas que le socket est fermé.

De plus, quel travailleur utilisez-vous ?

Oui, ce sont des codes d'erreur Heroku :
H12 - Request Timeout - généralement 30s (https://devcenter.heroku.com/articles/error-codes#h12-request-timeout)
H13 - Connexion fermée sans réponse - (https://devcenter.heroku.com/articles/error-codes#h13-connection-closed-without-response)

Edit: je viens de remarquer que gunicorn utilisera PORT s'il existe en tant que variable d'environnement, c'est donc ainsi que le port est configuré.

Nous utilisons des nœuds de calcul synchrones.

Et j'ai aussi oublié de mentionner, nous utilisons gunicorn 19.3.0

fermeture de l'émission car aucune activité ne s'y est produite depuis longtemps. Peut-être qu'avoir un délai d'attente retardé serait bon pour les applications à démarrage long, mais cela devrait être fait dans un autre ticket si nécessaire.

Hé, je suis également confronté au même problème avec gunicorn uvicorn sur heroku avec le procfile d'administration new-relic :

newrelic-admin run-program gunicorn -w 4 -k uvicorn.workers.UvicornWorker app.main:fastapi_app -b 0.0.0.0:${PORT:-5000} --log-level info --access-logfile=- --logger-class=gunicorn_color.Logger --preload

Cela m'amène à ce journal dès que le système est démarré :

2021-03-19T13:18:19.187532+00:00 heroku[web.1]: State changed from starting to up
2021-03-19T13:18:51.964740+00:00 heroku[router]: at=error code=H12 desc="Request timeout" method=GET path="/" host=api-app-clienti-pr-49.herokuapp.com request_id=8742009a-3e56-4f83-a147-97ff84d4e30b fwd="5.89.111.249" dyno=web.1 connect=1ms service=30003ms status=503 bytes=0 protocol=https
2021-03-19T13:19:04.292784+00:00 heroku[router]: at=error code=H12 desc="Request timeout" method=GET path="/api" host=api-app-clienti-pr-49.herokuapp.com request_id=85b6320a-7728-4074-87eb-b0992e7c3f9d fwd="5.89.111.249" dyno=web.1 connect=3ms service=30001ms status=503 bytes=0 protocol=https
Cette page vous a été utile?
0 / 5 - 0 notes