<p>gunicorn TIEMPO MUERTO DEL TRABAJADOR CRÍTICO</p>

Creado en 21 ene. 2017  ·  18Comentarios  ·  Fuente: benoitc/gunicorn

Estoy ejecutando un gunicorn con la siguiente configuración:
gunicorn --worker-class gevent --timeout 30 --graceful-timeout 20 --max-requests-jitter 2000 --max-requests 1500 -w 50 --log-level DEBUG --capture-output --bind 0.0.0.0:5000 run:app y veo en todos los trabajadores menos en 3 el [CRITICAL] WORKER TIMEOUT . Después de un tiempo, Gunicorn no puede generar más trabajadores o al menos es muy lento en generarlos. Esto hace que el servidor no sea accesible y cualquier solicitud sea inaccesible.

Reduje la cantidad de trabajadores a 3 y le di a cada trabajador 2 subprocesos y ahora ya no veo este problema.

No puedo obtener un seguimiento de pila de los tiempos de espera, pero parece que después de una cierta cantidad de trabajadores no puede manejarlos.

( unconfirmed - Bugs -

Comentario más útil

Cualquiera que aún tenga este problema, verifique la disponibilidad de recursos para la aplicación, además de aumentar el tiempo de espera y cambiar el tipo de clase de trabajador

Tenía este problema cuando intenté implementar mi aplicación usando Docker Swarm y me di cuenta de que estaba limitando el recurso demasiado bajo para la aplicación. Aumentar el recurso me resuelve el problema.

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

Creo que esto no es un error, solo la forma en que configuramos nuestras aplicaciones

Todos 18 comentarios

cuando se agota el tiempo de espera de un trabajador, significa que no notificó al árbitro a tiempo que estaba vivo. ¿Tiene alguna tarea ejecutada durante una solicitud que podría demorar más que el tiempo de espera?

@jseaidou golpe.

Perdón por la respuesta tardía @benoitc. El problema que estoy viendo es en realidad los subprocesos no activos que hacen esto. Mis subprocesos activos no se agotan, los no activos con menos carga dan más errores críticos de tiempo de espera que simplemente agotar el tiempo de espera. Cambié de gevent a tornado y eso parece haber solucionado el problema de bloqueo, pero sigo viendo a 3 trabajadores dando constantemente el tiempo de espera crítico cada 30 segundos. Si es un tiempo de espera normal, no debería ser un error crítico.

Estoy enfrentando exactamente el mismo problema.
Gunicorn 19.7.1
gevent 1.2.1
Python 3.5.3
Ejecutando en Docker, imagen basada en " python: 3.5 " oficial

@jseaidou es un tiempo de espera

Lo más probable es que uno de sus trabajadores esté realizando una operación de bloqueo que impida que el trabajador gunicorn notifique al árbitro. Si tiene una operación larga, asegúrese de activar el programador geven de vez en cuando durmiendo o tal. o cualquier cosa que llame al programador de tornados también.

¿Cómo puedo reproducir el problema?

@saabeilin mismo ^^

Veo lo mismo: los trabajadores se agotan incluso cuando no atienden solicitudes. Todo lo que hice fue lanzar mi contenedor en AWS ECS.

[2017-06-27 20:41:56 +0000] [1] [DEBUG] Current configuration:
proxy_protocol: False
worker_connections: 1000
statsd_host: None
max_requests_jitter: 0
post_fork: <function post_fork at 0x7f6bbc3f1938>
errorlog: -
enable_stdio_inheritance: False
worker_class: sync
ssl_version: 2
suppress_ragged_eofs: True
syslog: False
syslog_facility: user
when_ready: <function when_ready at 0x7f6bbc3f1668>
pre_fork: <function pre_fork at 0x7f6bbc3f17d0>
cert_reqs: 0
preload_app: False
keepalive: 2
accesslog: -
group: 0
graceful_timeout: 30
do_handshake_on_connect: False
spew: False
workers: 4
proc_name: None
sendfile: None
pidfile: None
umask: 0
on_reload: <function on_reload at 0x7f6bbc3f1500>
pre_exec: <function pre_exec at 0x7f6bbc3f1ed8>
worker_tmp_dir: None
limit_request_fields: 100
pythonpath: None
on_exit: <function on_exit at 0x7f6bbc3f7758>
config: None
logconfig: None
check_config: False
statsd_prefix:
secure_scheme_headers: {'X-FORWARDED-PROTOCOL': 'ssl', 'X-FORWARDED-PROTO': 'https', 'X-FORWARDED-SSL': 'on'}
reload_engine: auto
proxy_allow_ips: ['127.0.0.1']
pre_request: <function pre_request at 0x7f6bbc3f70c8>
post_request: <function post_request at 0x7f6bbc3f71b8>
forwarded_allow_ips: ['127.0.0.1']
worker_int: <function worker_int at 0x7f6bbc3f1c08>
raw_paste_global_conf: []
threads: 1
max_requests: 0
chdir: /opt/app
daemon: False
user: 0
limit_request_line: 4094
access_log_format: %(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s"
certfile: None
on_starting: <function on_starting at 0x7f6bbc3f1398>
post_worker_init: <function post_worker_init at 0x7f6bbc3f1aa0>
child_exit: <function child_exit at 0x7f6bbc3f7320>
worker_exit: <function worker_exit at 0x7f6bbc3f7488>
paste: None
default_proc_name: app:app
syslog_addr: udp://localhost:514
syslog_prefix: None
ciphers: TLSv1
worker_abort: <function worker_abort at 0x7f6bbc3f1d70>
loglevel: DEBUG
bind: ['0.0.0.0:5005']
raw_env: []
initgroups: False
capture_output: False
reload: False
limit_request_field_size: 8190
nworkers_changed: <function nworkers_changed at 0x7f6bbc3f75f0>
timeout: 30
keyfile: None
ca_certs: None
tmp_upload_dir: None
backlog: 2048
logger_class: gunicorn.glogging.Logger
[2017-06-27 20:41:56 +0000] [1] [INFO] Starting gunicorn 19.7.1
[2017-06-27 20:41:56 +0000] [1] [DEBUG] Arbiter booted
[2017-06-27 20:41:56 +0000] [1] [INFO] Listening at: http://0.0.0.0:5005 (1)
[2017-06-27 20:41:56 +0000] [1] [INFO] Using worker: sync
[2017-06-27 20:41:56 +0000] [8] [INFO] Booting worker with pid: 8
[2017-06-27 20:41:57 +0000] [9] [INFO] Booting worker with pid: 9
[2017-06-27 20:41:57 +0000] [10] [INFO] Booting worker with pid: 10
[2017-06-27 20:41:57 +0000] [12] [INFO] Booting worker with pid: 12
[2017-06-27 20:41:57 +0000] [1] [DEBUG] 4 workers
[2017-06-27 20:42:15 +0000] [10] [DEBUG] Closing connection.
[2017-06-27 20:42:15 +0000] [8] [DEBUG] Closing connection.
[2017-06-27 20:42:45 +0000] [8] [DEBUG] Closing connection.
[2017-06-27 20:42:45 +0000] [10] [DEBUG] Closing connection.
[2017-06-27 20:42:46 +0000] [1] [CRITICAL] WORKER TIMEOUT (pid:9)
[2017-06-27 20:42:46 +0000] [1] [CRITICAL] WORKER TIMEOUT (pid:12)
[2017-06-27 20:42:46 +0000] [9] [INFO] Worker exiting (pid: 9)
[2017-06-27 20:42:46 +0000] [12] [INFO] Worker exiting (pid: 12)
[2017-06-27 20:42:46 +0000] [1] [DEBUG] 3 workers
[2017-06-27 20:42:46 +0000] [24] [INFO] Booting worker with pid: 24
[2017-06-27 20:42:46 +0000] [25] [INFO] Booting worker with pid: 25
[2017-06-27 20:42:46 +0000] [1] [DEBUG] 4 workers

Esto no ocurre cuando se ejecuta localmente. : - /

Parece que cambiar a gevent trabajadores me lo ha resuelto. ¯ \ _ (ツ) _ / ¯

Duplicado del # 1194, creo.

He visto que esto sucede repetidamente últimamente, y para mí parece relacionado con poner la computadora portátil en suspensión. Cuando abro la tapa, aparecen varios de estos mensajes. No estoy seguro de que esto ayude, pero pensé en mencionarlo ...

gunicorn --daemon --workers 2 --timeout 120 --bind 127.0.0.1:4000 --pid /var/run/mshc_admin.pid --user danilovskoe --group danilovskoe --chdir / home / danilovskoe / mshc2 / src / flask / --env MSHC_PRODUCTION = / etc / monit / mshc.config.py admin_ gunicorn: aplicación

tiempo de espera 30 segundos
OBTENER solicitud

ubuntu 16.04
matraz 0.12.2
Python 3.6.3 (predeterminado, 4 de octubre de 2017, 02:55:45)
[GCC 5.4.0 20160609] en Linux
gunicorn (versión 19.7.1)

Me encontré con el problema.

Justo después de iniciar la aplicación, funciona. Pero solo si hay una solicitud, se activará [CRITICAL] WORKER TIMEOUT . Por ejemplo,

[2018-01-02 16:38:03 +0800] [24355] [INFO] Starting gunicorn 19.7.1
[2018-01-02 16:38:03 +0800] [24355] [DEBUG] Arbiter booted
[2018-01-02 16:38:03 +0800] [24355] [INFO] Listening at: http://0.0.0.0:8080 (24355)
[2018-01-02 16:38:03 +0800] [24355] [INFO] Using worker: gevent
[2018-01-02 16:38:03 +0800] [24358] [INFO] Booting worker with pid: 24358
[2018-01-02 16:38:03 +0800] [24355] [DEBUG] 1 workers

[2018-01-02 16:38:10 +0800] [24358] [DEBUG] GET /v1/bj2/CC/uuid
[2018-01-02 16:38:10 +0800] [24358] [DEBUG] Closing connection. 
[2018-01-02 16:38:41 +0800] [24355] [CRITICAL] WORKER TIMEOUT (pid:24358)
[2018-01-02 16:38:41 +0800] [24358] [INFO] Worker exiting (pid: 24358)
[2018-01-02 16:38:41 +0800] [24381] [INFO] Booting worker with pid: 24381

[2018-01-02 16:48:51 +0800] [24355] [CRITICAL] WORKER TIMEOUT (pid:24381)
[2018-01-02 16:48:51 +0800] [24381] [INFO] Worker exiting (pid: 24381)
[2018-01-02 16:48:51 +0800] [24703] [INFO] Booting worker with pid: 24703
[2018-01-02 16:48:51 +0800] [24703] [INFO] worker pid 24703 notify
[2018-01-02 16:48:51 +0800] [24703] [DEBUG] GET /v1/bj2/CC/uuid
[2018-01-02 16:48:51 +0800] [24703] [DEBUG] Closing connection. 
CentOS: 6.7
Python: 3.6.3
Gevent: 1.2.2
Greenlet: 0.4.9
Gunicorn: 19.7.1

RUN CMD: gunicorn --worker-class gevent --log-level debug --bind 0.0.0.0:8080 app

Cuando cambié la clase de trabajador a eventlet , eso es,
gunicorn --worker-class eventlet --log-level debug --bind 0.0.0.0:8080 app ,
está bien.

Aviso: Mi aplicación se ejecuta en el host físico, ni en el host virtual ni en el host en la nube.


Actualizar:

Entonces supongo que es la cuestión de gevent o gevent trabajador.

Hay informes sobre este tema de gevent resolviendo el problema y gevent causando el problema. No puedo identificar una causa raíz aquí. Algunos de los informes pueden ser los mismos que los del # 1194, pero otros tal vez no.

Si alguien puede compartir un caso mínimo para reproducir, eso ayudaría.

No estoy seguro de que sea definitivamente el mismo problema, pero puedo reproducirlo el 100% del tiempo usando Virtualbox con la siguiente configuración:

Anfitrión: Windows 10
Invitado: Ubuntu 16.04
Gunicorn: 19.7.1

Reenvío TCP: 8000 entre el host y el invitado a través de la conexión NAT predeterminada. Usando un trabajador sync , cualquier solicitud en el host de localhost:8000 hace que estos errores aparezcan en el registro, pero si hago las mismas solicitudes al invitado , el registro es claro. Cambiar a --worker-class eventlet elimina el rastro.

Aprecio que Virtualbox es una dimensión completamente diferente, pero suena muy similar a lo que se describe anteriormente, y es consistentemente reproducible (al menos para mí).

Veo que esto sucede con cargas lentas. Durante una carga (a un sitio de Django), si se agota el tiempo de espera del trabajador, la carga muere.

@lordmauve si está utilizando el trabajador de sincronización que se espera. Las solicitudes largas bloquearán al trabajador y, finalmente, el árbitro lo eliminará. Puede utilizar un tipo de trabajador diferente si espera que las solicitudes largas tengan éxito.

Para cualquiera que lea este hilo, vuelva a abrirlo con un estuche mínimo para reproducir. No veo ninguna investigación limpia que llevar a cabo aquí. Para el caso de AWS / ECS, todavía dejo el n. ° 1194 abierto hasta que pueda probar las configuraciones que enumeré (https://github.com/benoitc/gunicorn/issues/1194#issuecomment-371250650).

Cualquiera que aún tenga este problema, verifique la disponibilidad de recursos para la aplicación, además de aumentar el tiempo de espera y cambiar el tipo de clase de trabajador

Tenía este problema cuando intenté implementar mi aplicación usando Docker Swarm y me di cuenta de que estaba limitando el recurso demasiado bajo para la aplicación. Aumentar el recurso me resuelve el problema.

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

Creo que esto no es un error, solo la forma en que configuramos nuestras aplicaciones

@jseaidou es un tiempo de espera

Lo más probable es que uno de sus trabajadores esté realizando una operación de bloqueo que impida que el trabajador gunicorn notifique al árbitro. Si tiene una operación larga, asegúrese de activar el programador geven de vez en cuando durmiendo o tal. o cualquier cosa que llame al programador de tornados también.

¿Cómo puedo reproducir el problema?

@saabeilin mismo ^^

Gracias, esto tiene sentido.
Para mí, esto sucede al entregar un archivo grande que se descargó previamente del almacenamiento en la nube.
Previa solicitud, el archivo se recupera en el disco local desde el almacenamiento en la nube y luego se descifra al cliente. La descarga desde el almacenamiento en la nube funciona bien, incluso si lleva 10 minutos o más.
Una vez que el trabajador comienza a descifrar el archivo del disco al cliente, muere después de unos cientos de MB, probablemente porque se agota el tiempo de espera mientras está ocupado con esta operación de bloqueo.

¿Fue útil esta página
0 / 5 - 0 calificaciones