Error de tiempo de espera de trabajador de Gunicorn

182

He configurado gunicorn con 3 trabajadores 30 conexiones de trabajadores y uso de clase de trabajador eventlet. Está configurado detrás de Nginx. Después de cada pocas solicitudes, veo esto en los registros.

[ERROR] gunicorn.error: WORKER TIMEOUT (pid:23475)
None
[INFO] gunicorn.error: Booting worker with pid: 23514

¿Por qué está pasando esto? ¿Cómo puedo averiguar qué va mal?

Gracias

Juan
fuente
2
¿Pudiste resolver el problema? Por favor comparta sus pensamientos ya que también me quedé con eso. Gunicorn==19.3.1ygevent==1.0.1
Black_Rider
2
Encontré la solución para ello. Aumenté el tiempo de espera a un valor muy grande y luego pude ver el seguimiento de la pila
Black_Rider

Respuestas:

156

Tuvimos el mismo problema al usar Django + nginx + gunicorn. A partir de la documentación de Gunicorn, hemos configurado el elegante tiempo de espera que casi no hizo ninguna diferencia.

Después de algunas pruebas, encontramos la solución, el parámetro a configurar es: tiempo de espera (y no tiempo de espera agraciado). Funciona como un reloj ...

Entonces, haz:

1) abre el archivo de configuración gunicorn

2) configure el TIEMPO DE ESPERA según lo que necesite: el valor está en segundos

NUM_WORKERS=3
TIMEOUT=120

exec gunicorn ${DJANGO_WSGI_MODULE}:application \
--name $NAME \
--workers $NUM_WORKERS \
--timeout $TIMEOUT \
--log-level=debug \
--bind=127.0.0.1:9000 \
--pid=$PIDFILE
Amit Talmor
fuente
9
Gracias, esta es la respuesta correcta. Y luego, para ahorrar recursos con muchas conexiones concurrentes:, pip install geventluego worker_class geventen su archivo de configuración o -k geventen la línea de comando.
little_birdie
2
Estoy corriendo con el supervisor, así que lo agregué a conf.d / app.conf :command=/opt/env_vars/run_with_env.sh /path/to/environment_variables /path/to/gunicorn --timeout 200 --workers 3 --bind unix:/path/to/socket server.wsgi:application
lukik
31

En Google Cloud, simplemente agregue --timeout 90al punto de entrada enapp.yaml

entrypoint: gunicorn -b :$PORT main:app --timeout 90
Apoorv Agarwal
fuente
21

Ejecuta Gunicorn con --log-level=DEBUG.

Debería darte un seguimiento de la pila de aplicaciones.

gwik
fuente
41
No lo hace en mi caso.
Joe
16
ahora es--log-level debug
psychok7
44
Me encantaría obtener un seguimiento directo, pero ninguno de ellos trabaja aquí, usando gunicorn 19.4.5. Se muestra el material de depuración, por lo que supongo que se reconoció el indicador, pero no se apila el tiempo de espera.
orzel
6

Necesita usar otra clase de tipo trabajador, una asíncrona como gevent o tornado, vea esto para obtener más explicaciones: Primera explicación:

También es posible que desee instalar Eventlet o Gevent si espera que el código de su aplicación deba detenerse durante períodos prolongados durante el procesamiento de la solicitud

Segundo :

Los trabajadores síncronos predeterminados suponen que su aplicación está vinculada a recursos en términos de CPU y ancho de banda de red. En general, esto significa que su aplicación no debe hacer nada que lleve una cantidad de tiempo indefinida. Por ejemplo, una solicitud a Internet cumple con este criterio. En algún momento, la red externa fallará de tal manera que los clientes se acumularán en sus servidores.

Dseed
fuente
¿Cómo utilizaría una clase de trabajo tan diferente?
Frederick Nord el
6

Tuve un problema muy similar, también intenté usar "runserver" para ver si podía encontrar algo, pero todo lo que tenía era un mensaje Killed

Entonces pensé que podría ser un problema de recursos, y seguí adelante para darle más RAM a la instancia, y funcionó.

James Lin
fuente
1
Estaba viendo este problema incluso con gevent y el tiempo de espera establecido correctamente, el problema era la
falta
6

WORKER TIMEOUTsignifica que su aplicación no puede responder a la solicitud en un período de tiempo definido. Puede configurar esto usando la configuración de tiempo de espera de gunicorn . Algunas aplicaciones necesitan más tiempo para responder que otras.

Otra cosa que puede afectar esto es elegir el tipo de trabajador

Los trabajadores síncronos predeterminados suponen que su aplicación está vinculada a los recursos en términos de CPU y ancho de banda de red. En general, esto significa que su aplicación no debe hacer nada que lleve una cantidad de tiempo indefinida. Un ejemplo de algo que lleva una cantidad de tiempo indefinida es una solicitud a Internet. En algún momento, la red externa fallará de tal manera que los clientes se acumularán en sus servidores. Entonces, en este sentido, cualquier aplicación web que realice solicitudes salientes a las API se beneficiará de un trabajador asincrónico.

Cuando tuve el mismo problema que el tuyo (estaba tratando de implementar mi aplicación usando Docker Swarm), intenté aumentar el tiempo de espera y usar otro tipo de clase de trabajador. Pero todo falló.

Y de repente me di cuenta de que estaba limitando mi recurso demasiado bajo para el servicio dentro de mi archivo de redacción . Esto es lo que ralentizó la aplicación en mi caso

deploy:
  replicas: 5
  resources:
    limits:
      cpus: "0.1"
      memory: 50M
  restart_policy:
    condition: on-failure

Por lo tanto, le sugiero que compruebe qué cosa ralentiza su aplicación en primer lugar

hashlash
fuente
4

¿Este punto final toma demasiado tiempo?

Tal vez esté utilizando un matraz sin soporte asíncrono, por lo que cada solicitud bloqueará la llamada. Para crear soporte asíncrono sin dificultad, agregue el geventtrabajador.

Con gevent, una nueva llamada generará un nuevo hilo, y su aplicación podrá recibir más solicitudes

pip install gevent
gunicon .... --worker-class gevent
Ramon Medeiros
fuente
1
ajuste simple ... me salvó el día!
penduDev
3

Tengo el mismo problema en Docker.

En Docker mantengo LightGBMmodelos entrenados + Flasksolicitudes de servicio. Como servidor HTTP que utilicé gunicorn 19.9.0. Cuando ejecuté mi código localmente en mi computadora portátil Mac, todo funcionó a la perfección, pero cuando ejecuté la aplicación en Docker mis solicitudes POST JSON se congelaron por un tiempo, luegogunicorn trabajador había fallado con la [CRITICAL] WORKER TIMEOUTexcepción.

Intenté toneladas de enfoques diferentes, pero el único que resolvió mi problema fue agregar worker_class=gthread .

Aquí está mi configuración completa:

import multiprocessing

workers = multiprocessing.cpu_count() * 2 + 1
accesslog = "-" # STDOUT
access_log_format = '%(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(q)s" "%(D)s"'
bind = "0.0.0.0:5000"
keepalive = 120
timeout = 120
worker_class = "gthread"
threads = 3
Artem Zaika
fuente
votó por algunas de sus otras respuestas, así que esta no es suficiente: P
Achala Dissanayake
1

el tiempo de espera es un parámetro clave para este problema.

Sin embargo, no es adecuado para mí.

descubrí que no hay un error de tiempo de espera de gunicorn cuando configuro los trabajadores = 1.

cuando miro mi código, encontré algo de conexión de socket (socket.send & socket.recv) en el servidor init.

socket.recv bloqueará mi código y es por eso que siempre expira cuando los trabajadores> 1

espero dar algunas ideas a las personas que tienen algún problema conmigo

Mao
fuente
1

Esto funcionó para mí:

gunicorn app:app -b :8080 --timeout 120 --workers=3 --threads=3 --worker-connections=1000

Si tiene eventletagregar:

--worker-class=eventlet

Si tiene geventagregar:

--worker-class=gevent
Skerrepy
fuente
0

Para mí, la solución era agregar --timeout 90a mi punto de entrada, pero no funcionaba porque tenía DOS puntos de entrada definidos, uno en app.yaml y otro en mi Dockerfile. Eliminé el punto de entrada no utilizado y agregué --timeout 90el otro.

PV
fuente