Gunicorn: Tiempos de espera instantáneos de los trabajadores después de solicitudes de larga duración

Creado en 8 ago. 2013  ·  45Comentarios  ·  Fuente: benoitc/gunicorn

Hemos estado experimentando un problema muy extraño que involucra tiempos de espera de solicitud con Gunicorn ejecutándose frente a nuestra aplicación Django en Heroku.

En esencia, el problema ocurre cuando se realiza una solicitud de ejecución muy prolongada a la aplicación, lo que hace que se corte por el tiempo de espera de solicitud de nivel de

[CRITICAL] WORKER TIMEOUT (pid:15)

Esto da como resultado una página de error interno del servidor que se devuelve al cliente de inmediato. Este comportamiento no es coherente; a veces, la siguiente solicitud tendrá éxito, a veces no. Mi sospecha es que el error ocurrirá si la solicitud es manejada por el mismo trabajador de Gunicorn que estaba tratando con la solicitud de larga duración.

Estamos ejecutando Gunicorn directamente desde Django de la siguiente manera:

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

Otros parámetros de configuración relevantes, como worker_connections y max_requests, se establecen en sus valores predeterminados. Sin embargo, hemos experimentado cambiando esta configuración, así como el número de trabajadores, pero el problema descrito anteriormente ocurre en todos los casos que hemos intentado. Nuestra versión actual de Gunicorn es 0.14.6, y se revertió después de actualizar a 17.5 en caso de que esa fuera la fuente del problema. Desafortunadamente, el mismo comportamiento ocurre en ambas versiones.

Tenemos grandes dificultades para comprender la causa raíz de este problema. De la documentación de Heroku vinculada anteriormente:

Si bien el enrutador ha devuelto una respuesta al cliente, su aplicación no sabrá que la solicitud que está procesando ha agotado el tiempo de espera y su aplicación continuará funcionando en la solicitud.

Supongo que esto significa que, a pesar del hecho de que la solicitud original de larga duración se ha agotado desde la perspectiva del cliente, un trabajador de Gunicorn todavía está procesando la solicitud. Lo que me desconcierta es cómo esto causaría una nueva solicitud posterior para lanzar un tiempo de espera de trabajador de inmediato, dado que los trabajadores están usando gevent y, por lo tanto, subprocesos asíncronos para manejar las solicitudes. Hubiera pensado que la primera solicitud de larga duración sería

  1. sin bloqueo debido al hecho de que hay varios subprocesos de trabajo gevent, y
  2. asesinado por Gunicorn antes de que ocurra cualquier solicitud posterior, ya que el tiempo de espera de solicitud predeterminado para Gunicorn es de 30 segundos, idéntico al tiempo de espera de solicitud de Heroku.

Vale la pena mencionar que las solicitudes de larga duración se conectan a nuestra base de datos PostgreSQL y realizan varias consultas complejas. Los bloqueos parecen ocurrir solo después de que la conexión de larga duración se agota gracias a Heroku mientras se interactúa con la base de datos. Probamos esto en nuestro servidor de prueba creando dos vistas separadas, una de las cuales ejecuta consultas largas en la base de datos hasta que se alcanza un tiempo de espera de Heroku, y la otra simplemente espera más allá de la marca de 30 segundos para producir el tiempo de espera de Heroku. La vista anterior pudo provocar tiempos de espera de los trabajadores de Gunicorn en la siguiente solicitud, mientras que la vista 'inactiva' no lo fue.

Sería fantástico si alguien tuviera alguna idea del comportamiento subyacente que causa este problema; cualquier información adicional que pueda proporcionar para ayudar a diagnosticar el problema, hágamelo saber. Espero que esta sea la forma correcta de manejar este problema y que no se haya planteado ni abordado antes.

( FeaturWorker - Bugs -

Todos 45 comentarios

@Jwpe Excelente informe de errores.

Lo primero que analizaría es si está utilizando un controlador PostgreSQL ecológico. Solía ​​haber una versión específica que necesitabas usar con un parche de mono para que esto funcionara correctamente. No conozco el estado actual de las cosas ahora. Pero el tiempo de espera que pegó es un tiempo de espera de trabajador y en uno de los trabajadores asíncronos que básicamente se reduce a "un greenlet no ha cedido durante más de $ timeout segundos". Dado que está describiendo solicitudes de PostgreSQL de larga ejecución, ese es el primer lugar que investigaría.

@davisp ¡ Gracias por la rápida respuesta a esto!

Siguiendo su puntero, eché un vistazo al adaptador psycopg2, que usamos para conectar nuestra aplicación Django a Postgres, y descubrí esta sección de la documentación que dice:

Advertencia: las conexiones de Psycopg no son seguras para subprocesos verdes y no pueden ser utilizadas simultáneamente por diferentes subprocesos verdes. Intentar ejecutar más de un comando a la vez usando un cursor por hilo resultará en un error (o un punto muerto en las versiones anteriores a la 2.4.2).
Por lo tanto, se aconseja a los programadores que eviten compartir conexiones entre corrutinas o que utilicen un bloqueo compatible con la biblioteca para sincronizar las conexiones compartidas, por ejemplo, para la agrupación.

En otras palabras, a psycopg2 no le gustan los hilos verdes. Según el comportamiento que encontramos, supongo que esta es la fuente del error. La forma sugerida de lidiar con este problema, de acuerdo con los documentos de psycopg, es usar una biblioteca que habilite el soporte de psycopg para corrutinas. La biblioteca recomendada es psycogreen .

Intentaré recrear el problema en nuestro servidor de prueba utilizando la biblioteca psycogreen y veré si resuelve el problema. Ojalá pueda informar de algunos resultados relativamente pronto.

@Jwpe Eso parece el gancho que estaba recordando.

@benoitc ¿ Quizás deberíamos mencionar esto en los documentos de Gunicorn en algún lugar? Sin embargo, no estoy del todo seguro de cuál sería el mejor lugar.

¿@davisp tal vez en una sección de preguntas frecuentes?

hmppff. No estoy seguro, pero también podríamos mover en dicha sección cualquier información sobre virtualenv y otros trucos.

Tal vez una página de advertencias o "Notas sobre hilos verdes". No es muy urgente.

Estaba viendo prácticamente el mismo comportamiento exacto en Heroku ejecutando gunicorn con gevent trabajadores y algunos otros, así que cambié a trabajadores sincrónicos, como se recomienda en este hilo y seguía viendo básicamente el mismo problema grave. Obtendría un H12 de corte de Heroku de 30 segundos y luego repetí los errores de H12 y [CRITICAL] Worker Timeout hasta que restableciera todo el dinamómetro (a veces una hora o más después o hasta que se alcanzaran las solicitudes máximas). Así que reduje el tiempo de espera de gunicorn a 28 segundos para que se agotara antes de que Heroku lo cortara. El mismo problema (o muy similar) ocurre una o dos veces al día y persiste hasta que se reinicia el proceso maestro, solo que esta vez comienza con un H13 (conexión cerrada) ya que gunicorn lo está cortando. No hay un aumento significativo en el tráfico durante esos momentos.

Aquí está mi entrada de procfile actual:

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

Detalle de la serie de eventos:

Primero, recibo algunas solicitudes que parecen tardar mucho (más de 5 segundos), luego una solicitud falla con un tiempo de espera H12 (el tiempo de espera del trabajador lo corta) y algunas solicitudes más finalizarán, pero con tiempos excepcionalmente largos (20 segundos). A partir de entonces, es puro H11 30 segundos de corte heroku hasta que reinicio el dinamómetro.

Usamos gunicorn (v 18.0) como nuestro servidor web (que ejecuta python / django).

Ejecutamos newrelic, que muestra el tiempo de inactividad y los tiempos de espera de solicitudes increíblemente elevados, pero no ofrece otra información. No hubo picos en el rendimiento ni otras condiciones anormales que pueda ver en NR. Usamos papertrail para el procesamiento de registros y para enviar correos electrónicos de error.

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
Y esta "espiral de muerte" de H12 Time-outs y [CRITICAL] WORKER TIMEOUT continúa una y otra vez hasta que se reinicia el proceso maestro.

¿Alguna idea de si este es el mismo problema o uno diferente? ¿Alguna sugerencia para solucionarlo? Creo que dado que gunicorn está matando los procesos de trabajo después de que se agote el tiempo y comenzando de nuevo, podrían comenzar a procesar las cosas normalmente, pero parece que las solicitudes ni siquiera les llegan después de eso. Quizás sea un problema de Heroku.

: +1: También estoy viendo este problema.

También veo este problema en Heroku.

@sprynmr @richardkeen puede compartir la forma en que están poniendo en marcha gunicorn y cualquier registro que puede? Ayudaría mucho a solucionar el problema.

@nebstrebor ¿y si no limita el número de solicitudes?

Lo estábamos lanzando así:
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

Incluso con DEBUG a nivel de registro, no obtuvimos muchos registros sobre lo que estaba sucediendo. No usar gevent ha resuelto el problema por ahora, pero no es lo ideal.

@sprynmr ¿y si elimina el número máximo de solicitudes? Además, ¿qué versión de gevent?

Estábamos en 1.0rc2 . No estoy seguro del número máximo de solicitudes. Realmente no quiero volver a activarlo para nuestro entorno de producción en este momento.

Al leer la página de Heroku sobre el tiempo de espera de la well under 30 seconds, such as 10 or 15 espera de la aplicación

De todos modos, el problema que aparece con gevent probablemente se deba a la forma en que se manejan las conexiones. La versión actual del trabajador está generando un greenlet / conexiones aceptadas sin ninguna supervisión real de este greenlet. Lo que probablemente suceda es que uno de los conectores aceptados estará esperando durante mucho tiempo y no se manejan otros eventos, lo que hace que el trabajador de gunicorn se reinicie. Pero necesito comprobar ...

Interesante. No, no lo intentamos.

: +1: También veo esto en mi aplicación. @Jwpe / @sprynmr ¿Alguna vez llegó a una resolución sobre este problema? Parece que han pasado más de 2 meses desde que se produjo alguna actividad relacionada con este problema. Estoy ansioso por saber si encontró algo para solucionar el problema.

¡Gracias!

@dencold ¿probaste https://github.com/benoitc/gunicorn/issues/588#issuecomment -29267541

No tengo una cuenta en heroku, así que no estoy seguro de lo que hace. ¿También tienes los mismos registros?

Hola @benoitc , informaron @Jwpe y @nebstrebor . Me complace extraer las partes relevantes y agregarlas aquí si eso ayudaría a aislar el problema, solo hágamelo saber.

Voy a seguir su consejo de su comentario anterior y configurar el tiempo de espera de gunicorn para que sea más bajo que el tiempo de espera del enrutador heroku y ver si eso ayuda. Gracias por la sugerencia.

Sería útil averiguar la causa real de esta falla en cascada. Es realmente extraño ver a un trabajador fallar y luego hacer que todo el servidor de gunicorn no responda por completo. Avíseme si hay algo que pueda hacer para ayudar a diagnosticar. No puedo reproducir este tiempo de espera localmente. Parece que solo ocurre en la infraestructura de heroku.

Lo siento @dencold , nunca encontré una solución. Parecía un error misterioso muy profundo, y no tuve tiempo de luchar con él. Tendrá curiosidad por ver si el bit de tiempo de espera le ayuda. Informar.

@dencold , ¿también estás usando una nueva reliquia?

@benoitc sí, también estamos usando una nueva reliquia.

@dencold del mismo modo, nunca

@Jwpe , ¿al menos

Reduje el tiempo de corte a 15 segundos y seguía viendo el problema.

El domingo 26 de enero de 2014, Benoit Chesneau [email protected]
escribió:

@Jwpe https://github.com/Jwpe ¿al menos probaste el propuesto
¿solución? Además, el resultado es extraño y nunca lo reproduzco con gunicorn.
por sí mismo.

-
Responda a este correo electrónico directamente o véalo en Gi
.

Ben Roberts
CTO
Nutrislice, Inc.
866-524-3444 ext 702
[email protected]

@Jwpe / @nebstrebor muchas gracias por responder a este problema.

@benoitc hemos implementado la solución de tiempo de espera propuesta en nuestra instancia de heroku. Estaré atento a esto durante los próximos días. Volveré a publicar si veo que aparece el mismo problema después de que se haya establecido el nuevo tiempo de espera.

Gracias de nuevo a todos por la ayuda. Es bueno saber que no soy el único que tiene este problema. Espero que podamos llegar al fondo de la causa.

@benoitc solo quería informar que han pasado aproximadamente dos semanas con el tiempo de espera más bajo en su lugar. Hemos visto un par de tiempos de espera de trabajadores, pero ninguno que provoque que todo el proceso de gunicorn deje de responder. Esto parece resolver el problema, pero todavía no estoy seguro de por qué los tiempos de espera de 30 segundos estaban causando el error en cascada en primer lugar.

Solo quería mantenerte informado. ¡Gracias de nuevo por toda la ayuda aquí!

Tener el mismo error [CRITICAL] WORKER TIMEOUT al ejecutar Django con gunicorn en una Raspberry PI.

No hay noticias.

Estoy obteniendo el mismo TIEMPO MUERTO [CRÍTICO] PARA TRABAJADORES.
El problema es que después del tiempo de espera real del trabajador (solicitud larga), el gunicorn mata al trabajador e intenta generar uno nuevo, pero el nuevo trabajador no puede comenzar dentro del límite de TIMEOUT y no llega al lugar donde informa al proceso padre que es live, por lo que el gunicorn lo mata una y otra vez :(. En nuestro caso, el problema estaba relacionado con Gevent y Sentry (https://github.com/getsentry/raven-python/issues/305). Sentry simplemente cuelga el inicio .
Por cierto, será útil tener un tiempo de espera separado para la hora de inicio del trabajador y algunos registros adicionales dentro de un trabajador que no puede iniciar dentro de un tiempo de "tiempo de espera".

El tiempo de espera no es un tiempo de espera de solicitud excepto en el trabajador de sincronización. Los otros trabajadores siguen latiendo con el árbitro incluso cuando manejan solicitudes largas. El tiempo de espera es el tiempo de espera de inicio en ese caso.

En cierto sentido, no hay "solicitud de tiempo de espera" en gunicorn.

sí, el tiempo de espera del trabajador difiere del tiempo de espera de la solicitud en async. Pero las solicitudes de ejecución prolongada sin ninguna llamada de función donde puede ocurrir un "cambio de contexto" asíncrono (como "socket - lectura / escritura") son las causas de los tiempos de espera de los trabajadores. Y además, puede haber un tiempo de espera en el inicio del trabajador (donde no hay ninguna solicitud). Pero en los registros de Gunicorn no hay forma de distinguir esos 2 casos diferentes, solo hay un mensaje "WORKER TIMEOUT".

¿Deberíamos agregar una configuración de tiempo de espera de solicitud? Eso permitiría que las aplicaciones con inicios prolongados superen el tiempo de espera del trabajador.

No lo creo, por
1) Medir el tiempo de ejecución de la solicitud es difícil, no podemos usar la diferencia de tiempo al principio y al final de la solicitud.
2) Como sé, la captura de tiempos de espera de "unidades de ejecución" (la cantidad de código que se ejecuta entre el cambio de contexto) no es posible en gevent.

¿Alguna sugerencia entonces?

Si este problema se debe solo a tiempos de espera legítimos y potencialmente en cascada
tiempos de espera debido a la carga del servidor que no existe en la primera ejecución, ¿hay
algo que hacer aqui? ¿O se puede cerrar este problema y se maneja mejor?
operacionalmente en un nivel diferente de infraestructura?
El 30 de julio de 2014 a la 1:14 p.m., "Mkrtich" [email protected] escribió:

No lo creo, por
1) Medir el tiempo de ejecución de la solicitud es difícil, no podemos usar la diferencia de tiempo en el
mendicidad y al final de la solicitud.
2) Como sé, la captura de tiempos de espera de "unidades de ejecución" (la cantidad de código
que se ejecuta entre el cambio de contexto) no es posible en gevent.

-
Responda a este correo electrónico directamente o véalo en GitHub
https://github.com/benoitc/gunicorn/issues/588#issuecomment -50673040.

La sugerencia es tener 2 parámetros de tiempo de espera y 2 registros diferentes.
1) Uno es el parámetro de tiempo de espera actual que funcionará solo durante el manejo de solicitudes.
2) El segundo será el tiempo de espera de inicio del trabajador.

También viendo este problema

Terminamos cambiando a uWSGI para Heroku y hemos tenido más éxito ... no es una solución para Gunicorn, me doy cuenta, pero pensé que la sugerencia podría ser útil para alguien que está viendo este problema en su servidor de producción y necesita una resolución más temprano que tarde. .

@nebstrebor bien, ¿

@CrazyPython el ticket ha sido cerrado. ¿Puede abrir un nuevo ticket que describa el problema que tiene y cómo podemos reproducirlo? Definitivamente ayudaría a determinar si es el mismo problema, algo más y co :)

Sí, no hizo ninguna diferencia, como se señaló anteriormente. El problema fue esporádico
lo suficientemente (nunca fue capaz de reproducirse) y lo suficientemente catastrófico que tuvimos que
haz ese movimiento (ha pasado más de un año). Aunque realmente me gusta Gunicorn,
y lo usamos fuera de Heroku sin problemas.

Ben Roberts
CTO y cofundador
Nutrislice, Inc.
[email protected]
celular - 801-735-7845

El martes 30 de junio de 2015 a las 8:08 a.m., Benoit Chesneau [email protected]
escribió:

@nebstrebor https://github.com/nebstrebor bueno, ¿ probaste el
sugerencia para reducir el tiempo de espera?

@CrazyPython https://github.com/CrazyPython el ticket se ha cerrado.
¿Puede abrir un nuevo ticket, describir el problema que tiene y cómo podemos
reproducirlo? Definitivamente ayudaría a determinar si es el mismo problema,
algo más y co :)

-
Responda a este correo electrónico directamente o véalo en GitHub
https://github.com/benoitc/gunicorn/issues/588#issuecomment -117199606.

Creo que también estamos viendo este problema. Ambos trabajadores (--workers 2) se obsesionaron con algunas solicitudes de larga duración, eventualmente fueron asesinados (--timeout 20) e inmediatamente vemos dos H13, y luego comenzamos a reiniciar H12s & WORKER TIMEOUT. Durante los siguientes 10 minutos, continuó, los trabajadores nunca procesaron con éxito una solicitud antes de que alcanzaran el tiempo de espera y se reiniciaran. Entonces, reiniciamos el banco de pruebas y eso lo solucionó.

Una cosa interesante que noté que no vi a nadie más nota: vemos dos H13 (Conexión cerrada sin respuesta) al comienzo del problema, y ​​luego, cuando finalmente emitimos el SIGTERM, vimos una avalancha de H13 - 48 para ser exactos, que es el mismo número de TIEMPOS DE TRABAJO que vimos (excluyendo los dos primeros para los que vimos un H13 inmediato). No estoy exactamente seguro de lo que eso significa, pero parece sospechoso ...

¿Qué es H13s o H12s? ¿Es esto algo de heroku? ¿Cómo se da el puerto al que se dirigirá Gunicorn? Sospecho que el proxy heroku no detecta que el socket está cerrado.

Además, ¿qué trabajador estás usando?

Sí, son códigos de error de Heroku:
H12: tiempo de espera de solicitud: generalmente 30 s (https://devcenter.heroku.com/articles/error-codes#h12-request-timeout)
H13 - Conexión cerrada sin respuesta - (https://devcenter.heroku.com/articles/error-codes#h13-connection-closed-without-response)

Editar: Acabo de notar que gunicorn usará PORT si existe como una variable de entorno, así es como se configura el puerto.

Estamos usando trabajadores sincrónicos.

Y también me olvidé de mencionar que estamos ejecutando gunicorn 19.3.0

cerrando el issu ya que no había actividad allí desde hace mucho tiempo. Quizás tener un tiempo de espera retrasado sería bueno para aplicaciones de inicio prolongado, pero eso debería hacerse en otro ticket si es necesario.

Oye, también estoy enfrentando el mismo problema con gunicorn uvicorn en heroku con el procfile de administrador de nueva reliquia:

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

Esto me lleva a este registro tan pronto como se inicia el sistema:

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
¿Fue útil esta página
0 / 5 - 0 calificaciones