Estoy intentando instalar Gunicorn en Docker. Funciona bien a nivel local y la imagen de producción es exactamente la misma que la imagen local, pero obtengo este comportamiento extraño en el motor de producción de Docker:
ml-server_1 | [2017-12-11 13:18:50 +0000] [1] [INFO] Starting gunicorn 19.7.1
ml-server_1 | [2017-12-11 13:18:50 +0000] [1] [DEBUG] Arbiter booted
ml-server_1 | [2017-12-11 13:18:50 +0000] [1] [INFO] Listening at: http://0.0.0.0:80 (1)
ml-server_1 | [2017-12-11 13:18:50 +0000] [1] [INFO] Using worker: sync
ml-server_1 | [2017-12-11 13:18:50 +0000] [8] [INFO] Booting worker with pid: 8
ml-server_1 | [2017-12-11 13:18:50 +0000] [1] [DEBUG] 1 workers
ml-server_1 | Using TensorFlow backend.
ml-server_1 | [2017-12-11 13:18:54 +0000] [11] [INFO] Booting worker with pid: 11
ml-server_1 | Using TensorFlow backend.
ml-server_1 | [2017-12-11 13:18:58 +0000] [14] [INFO] Booting worker with pid: 14
ml-server_1 | Using TensorFlow backend.
ml-server_1 | [2017-12-11 13:19:02 +0000] [17] [INFO] Booting worker with pid: 17
ml-server_1 | Using TensorFlow backend.
Parece que gunicorn está arrancando a los trabajadores cada 4-5 segundos, a pesar de que no hay mensajes de error aparentes o señales de salida. Este comportamiento continúa indefinidamente hasta que se termina.
¿Es posible que un trabajador pueda salir sin registrar nada en stderr / stdout, o que el árbitro genere trabajadores infinitamente?
Dado que son la misma imagen de la ventana acoplable, están ejecutando exactamente el mismo código, exactamente en la misma arquitectura, por lo que estoy realmente confundido sobre qué podría ser esto (¿error?). ¡Cualquier ayuda muy apreciada!
ssh
-ing en el contenedor de Docker me llevó a encontrar este error:
Illegal instruction (core dumped)
¿Quizás Gunicorn debería sacar a la luz errores como este en lugar de tragarlos, o manejarlos de manera diferente? No estoy seguro, ¡solo pensé en plantear esto ya que podría ayudar a alguien más!
Gracias por informar del problema.
Si puede averiguar dónde sucede esto, sería muy útil.
Quizás podamos agregar el registro cuando los trabajadores salgan. Por lo general, el propio trabajador registra, pero si se mata de forma muy abrupta, no lo hará.
¡No hay problema!
Parece que hay un problema con Spacy que acabo de agregar a este hilo: https://github.com/explosion/spaCy/issues/1589
De todos modos, está causando un SIGILL
como strace
confirma:
--- SIGILL {si_signo=SIGILL, si_code=ILL_ILLOPN, si_addr=0x7ff48bbe6cea} ---
+++ killed by SIGILL (core dumped) +++
Illegal instruction (core dumped)
Supongo que sería bueno si gunicorn pudiera identificar esto y registrar un error en lugar de reiniciar el trabajador de manera fantasma, ¡pero sé muy poco sobre cómo funcionan los códigos de salida!
Algunos códigos de salida definitivamente tienen significados especiales y probablemente podríamos registrarlos.
http://tldp.org/LDP/abs/html/exitcodes.html
¡Suena bien! Además, si el código de salida no es un código de salida reservado (como en este caso), sería genial si pudiera registrarse (sin una explicación) para que sea evidente que el trabajador está terminando 🙂
Tengo un problema similar, gunicorn arranca un nuevo trabajador siempre que hago una solicitud http. No obtengo ninguna respuesta, solo reinicia el nuevo trabajador siempre. Registro de Strace de dos solicitudes http:
select(4, [3], [], [], {1, 0}) = 0 (Timeout)
fstat(6, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
fstat(7, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
fstat(9, {st_mode=S_IFREG, st_size=0, ...}) = 0
fstat(8, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
select(4, [3], [], [], {1, 0}) = ? ERESTARTNOHAND (To be restarted if no handler)
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_KILLED, si_pid=510, si_uid=0, si_status=SIGSEGV, si_utime=160, si_stime=32} ---
getpid() = 495
rt_sigreturn({mask=[]}) = -1 EINTR (Interrupted system call)
wait4(-1, [{WIFSIGNALED(s) && WTERMSIG(s) == SIGSEGV && WCOREDUMP(s)}], WNOHANG, NULL) = 510
lseek(8, 0, SEEK_CUR) = 0
close(8) = 0
wait4(-1, 0x7ffd455ad844, WNOHANG, NULL) = 0
write(4, ".", 1) = 1
select(4, [3], [], [], {0, 840340}) = 1 (in [3], left {0, 840338})
read(3, ".", 1) = 1
read(3, 0x7f2682025fa0, 1) = -1 EAGAIN (Resource temporarily unavailable)
fstat(6, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
fstat(7, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
fstat(9, {st_mode=S_IFREG, st_size=0, ...}) = 0
umask(0) = 022
getpid() = 495
open("/tmp/wgunicorn-q4aa72u7", O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW|O_CLOEXEC, 0600) = 8
fcntl(8, F_SETFD, FD_CLOEXEC) = 0
chown("/tmp/wgunicorn-q4aa72u7", 0, 0) = 0
umask(022) = 0
unlink("/tmp/wgunicorn-q4aa72u7") = 0
fstat(8, {st_mode=S_IFREG|0600, st_size=0, ...}) = 0
ioctl(8, TIOCGWINSZ, 0x7ffd455b8e50) = -1 ENOTTY (Not a tty)
lseek(8, 0, SEEK_CUR) = 0
lseek(8, 0, SEEK_CUR) = 0
rt_sigprocmask(SIG_BLOCK, ~[], [], 8) = 0
fork() = 558
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
select(0, NULL, NULL, NULL, {0, 37381}[2017-12-28 17:50:23 +0000] [558] [INFO] Booting worker with pid: 558
) = 0 (Timeout)
select(4, [3], [], [], {1, 0}loading test-eu-ovh settings
) = 0 (Timeout)
fstat(6, {st_mode=S_IFREG, st_size=0, ...}) = 0
fstat(7, {st_mode=S_IFREG, st_size=0, ...}) = 0
fstat(9, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
fstat(8, {st_mode=S_IFREG|0600, st_size=0, ...}) = 0
select(4, [3], [], [], {1, 0}
) = 0 (Timeout)
fstat(6, {st_mode=S_IFREG, st_size=0, ...}) = 0
fstat(7, {st_mode=S_IFREG, st_size=0, ...}) = 0
fstat(9, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
fstat(8, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
select(4, [3], [], [], {1, 0}) = 0 (Timeout)
fstat(6, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
fstat(7, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
fstat(9, {st_mode=S_IFREG, st_size=0, ...}) = 0
fstat(8, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
select(4, [3], [], [], {1, 0}) = 0 (Timeout)
fstat(6, {st_mode=S_IFREG, st_size=0, ...}) = 0
fstat(7, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
fstat(9, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
fstat(8, {st_mode=S_IFREG, st_size=0, ...}) = 0
select(4, [3], [], [], {1, 0}) = 0 (Timeout)
fstat(6, {st_mode=S_IFREG, st_size=0, ...}) = 0
fstat(7, {st_mode=S_IFREG, st_size=0, ...}) = 0
fstat(9, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
fstat(8, {st_mode=S_IFREG, st_size=0, ...}) = 0
select(4, [3], [], [], {1, 0}) = 0 (Timeout)
fstat(6, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
fstat(7, {st_mode=S_IFREG, st_size=0, ...}) = 0
fstat(9, {st_mode=S_IFREG, st_size=0, ...}) = 0
fstat(8, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
select(4, [3], [], [], {1, 0}) = 0 (Timeout)
fstat(6, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
fstat(7, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
fstat(9, {st_mode=S_IFREG, st_size=0, ...}) = 0
fstat(8, {st_mode=S_IFREG, st_size=0, ...}) = 0
select(4, [3], [], [], {1, 0}) = ? ERESTARTNOHAND (To be restarted if no handler)
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_KILLED, si_pid=499, si_uid=0, si_status=SIGSEGV, si_utime=160, si_stime=31} ---
getpid() = 495
rt_sigreturn({mask=[]}) = -1 EINTR (Interrupted system call)
wait4(-1, [{WIFSIGNALED(s) && WTERMSIG(s) == SIGSEGV && WCOREDUMP(s)}], WNOHANG, NULL) = 499
lseek(7, 0, SEEK_CUR) = 0
close(7) = 0
wait4(-1, 0x7ffd455ad844, WNOHANG, NULL) = 0
write(4, ".", 1) = 1
select(4, [3], [], [], {0, 450691}) = 1 (in [3], left {0, 450689})
read(3, ".", 1) = 1
read(3, 0x7f2682067de8, 1) = -1 EAGAIN (Resource temporarily unavailable)
fstat(6, {st_mode=S_IFREG, st_size=0, ...}) = 0
fstat(9, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
fstat(8, {st_mode=S_IFREG, st_size=0, ...}) = 0
umask(0) = 022
getpid() = 495
open("/tmp/wgunicorn-5x9a40ca", O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW|O_CLOEXEC, 0600) = 7
fcntl(7, F_SETFD, FD_CLOEXEC) = 0
chown("/tmp/wgunicorn-5x9a40ca", 0, 0) = 0
umask(022) = 0
unlink("/tmp/wgunicorn-5x9a40ca") = 0
fstat(7, {st_mode=S_IFREG|0600, st_size=0, ...}) = 0
ioctl(7, TIOCGWINSZ, 0x7ffd455b8e50) = -1 ENOTTY (Not a tty)
lseek(7, 0, SEEK_CUR) = 0
lseek(7, 0, SEEK_CUR) = 0
rt_sigprocmask(SIG_BLOCK, ~[], [], 8) = 0
fork() = 579
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
select(0, NULL, NULL, NULL, {0, 8144}[2017-12-28 17:50:30 +0000] [579] [INFO] Booting worker with pid: 579
) = 0 (Timeout)
select(4, [3], [], [], {1, 0}) = 0 (Timeout)
fstat(6, {st_mode=S_IFREG, st_size=0, ...}) = 0
fstat(7, {st_mode=S_IFREG|0600, st_size=0, ...}) = 0
fstat(9, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
fstat(8, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
Estoy enfrentando el mismo problema, gunicorn
se inicia repetidamente en segundos para el tipo de trabajador sync
. Establecer el tiempo de espera del trabajador en 900
no ayuda.
En mi carga antes de la acción, estoy descargando datos de AWS S3. Se tarda aproximadamente 1 minuto y 10 segundos en descargar los distintos archivos.
@ sara-02 ¿cuál es tu línea de comando para lanzar gunicorn?
@benoitc gunicorn --pythonpath /src -b 0.0.0.0:$SERVICE_PORT --workers=1 -k sync -t $SERVICE_TIMEOUT flask_endpoint:app
Presente aquí
@ sara-02 Gracias.
¿Los trabajadores antiguos realmente están saliendo o se mantienen en línea y se generan nuevos trabajadores? ¿Qué muestra también el registro de depuración?
Los registros se mezclan con los registros de botocore, pero es algo como esto
[INFO] Booting worker with pid: a
[INFO] Booting worker with pid: b
[INFO] Booting worker with pid: c
pero ¿el trabajador es asesinado? ¿Qué devuelve el comando ps ax|grep gunicorn
?
@benoitc
Sin embargo, una pregunta, ¿por qué vemos 2 gunicorn
procesos, cuando el límite de trabajadores se establece en 1? ¿Es un maestro y un trabajador?
Hay 1 proceso de árbitro (maestro) y N procesos de trabajo ye :)
Entonces, ejecuta el comando cada vez que un trabajador arranca, ¿verdad? Si es así, parece que el trabajador mayor muere, se genera uno nuevo. Yo investigaré.
@ sara-02 una última cosa, ¿esto también está sucediendo en Docker?
@benoitc en docker-compose
está funcionando como se esperaba, pero cuando pongo el mismo código en Openshift
, veo este error. El aumento del requisito de memoria se solucionó, pero cuando ejecuto la aplicación a través de docker-compose
, está usando menos de limited
memoria.
Solo una actualización, el problema para mí era en realidad un error de memoria y se solucionó cuando se solucionó el problema de memoria.
@benoitc
Estoy enfrentando el mismo problema al intentar generar 5 trabajadores gunicorn en Docker.
@ sara-02
¿Cómo identificaste la causa de un error de memoria?
@ gulshan-gaurav 2 cosas me ayudaron:
Aumenté la memoria asignada a mi Pod y dejé de fallar. En segundo lugar, verificamos nuestros registros de Openshift Zabbix.
@ sara-02
Incluso en mi Pod de ensayo, los archivos + modelos que estoy cargando en la memoria ascienden a 50 Mb, por lo que 2 GB de memoria deberían ser suficientes para 5 trabajadores.
@ gulshan-gaurav ¿a qué problema te enfrentas? Tener 5 procesos allí se ve bien ...
Tuve el mismo problema. No encontré el problema exacto, pero se resolvió una vez que actualicé de Python 3.5 a 3.6.
Estoy enfrentando el mismo problema en un contenedor Docker. Gunicorn sigue molestando a un nuevo trabajador cada vez que llamo a un punto final que causa la falla, pero no se genera una excepción o un error en los archivos de registro de Gunicorn. Las cosas que elijo imprimir se registran y, de repente, el archivo de registro dice "Arrancando trabajador con pid ..."
Un paso que ayudó fue agregar la variable env PYTHONUNBUFFERED. Antes de eso, incluso las declaraciones impresas desaparecerían y no se guardarían en los registros de Gunicorn.
Otros 2 puntos finales de la aplicación funcionan correctamente.
Ejecuto Gunicorn con: gunicorn run: app -b localhost: 5000 --enable-stdio-heritage --error-logfile /var/log/gunicorn/error.log --access-logfile / var / log / gunicorn / access. log --capture-output - depuración a nivel de registro
Ya está ejecutando Python 3.6 y comprobado con top que la memoria no parece ser un problema.
EDITAR: Parece que fue un problema de Python y no una culpa de Gunicorn. Algunas discrepancias de versiones estaban causando que Python simplemente muriera sin dejar rastro mientras realizaba una determinada operación.
Estoy enfrentando un problema similar en el que el nodo trabajador sigue apareciendo
Booting worker with pid: 17636
. No sé si está matando al nodo trabajador anterior o si aún existe un nodo trabajador anterior. Pero la cantidad de trabajadores mencionados en los argumentos de la línea de comandos de gunicorn es solo 3 - -workers=3
. También estoy usando Python versión 3.7
Tuve una falta de coincidencia de dependencia de scikit-learn, pero incluso después de resolver eso, sigo recibiendo los mismos trabajadores infinitos. ¿Qué tipo de discrepancias en la versión de Python debo buscar y cómo identificarlas?
Estoy enfrentando el mismo problema dentro de OpenShift.
Como puede ver en la imagen, estoy usando 6 trabajadores (estaba probando con 3).
Aumenté la memoria de la cápsula y no funcionó.
BuildConfig:
¿Alguna idea?
Gracias
¿estás ejecutando esto en aws detrás de elb? Resolví ese problema colocando el ingreso de nginx entre elb y gunicorn
Tiene el mismo problema.
flask_1 | [2019-02-23 09:08:17 +0000] [1] [INFO] Starting gunicorn 19.9.0
flask_1 | [2019-02-23 09:08:17 +0000] [1] [INFO] Listening at: http://0.0.0.0:5000 (1)
flask_1 | [2019-02-23 09:08:17 +0000] [1] [INFO] Using worker: sync
flask_1 | [2019-02-23 09:08:17 +0000] [8] [INFO] Booting worker with pid: 8
flask_1 | [2019-02-23 09:08:19 +0000] [12] [INFO] Booting worker with pid: 12
flask_1 | [2019-02-23 09:08:19 +0000] [16] [INFO] Booting worker with pid: 16
flask_1 | [2019-02-23 09:08:20 +0000] [20] [INFO] Booting worker with pid: 20
flask_1 | [2019-02-23 09:08:21 +0000] [24] [INFO] Booting worker with pid: 24
flask_1 | [2019-02-23 09:08:22 +0000] [28] [INFO] Booting worker with pid: 28
flask_1 | [2019-02-23 09:08:23 +0000] [32] [INFO] Booting worker with pid: 32
flask_1 | [2019-02-23 09:08:25 +0000] [36] [INFO] Booting worker with pid: 36
flask_1 | [2019-02-23 09:08:26 +0000] [40] [INFO] Booting worker with pid: 40
flask_1 | [2019-02-23 09:08:27 +0000] [44] [INFO] Booting worker with pid: 44
flask_1 | [2019-02-23 09:08:29 +0000] [48] [INFO] Booting worker with pid: 48
flask_1 | [2019-02-23 09:08:30 +0000] [52] [INFO] Booting worker with pid: 52
flask_1 | [2019-02-23 09:08:31 +0000] [56] [INFO] Booting worker with pid: 56
flask_1 | [2019-02-23 09:08:33 +0000] [60] [INFO] Booting worker with pid: 60
flask_1 | [2019-02-23 09:08:34 +0000] [64] [INFO] Booting worker with pid: 64
flask_1 | [2019-02-23 09:08:35 +0000] [68] [INFO] Booting worker with pid: 68
flask_1 | [2019-02-23 09:08:36 +0000] [72] [INFO] Booting worker with pid: 72
flask_1 | [2019-02-23 09:08:37 +0000] [76] [INFO] Booting worker with pid: 76
flask_1 | [2019-02-23 09:08:38 +0000] [80] [INFO] Booting worker with pid: 80
flask_1 | [2019-02-23 09:08:40 +0000] [84] [INFO] Booting worker with pid: 84
flask_1 | [2019-02-23 09:08:41 +0000] [88] [INFO] Booting worker with pid: 88
flask_1 | [2019-02-23 09:08:42 +0000] [92] [INFO] Booting worker with pid: 92
flask_1 | [2019-02-23 09:08:44 +0000] [96] [INFO] Booting worker with pid: 96
flask_1 | [2019-02-23 09:08:45 +0000] [100] [INFO] Booting worker with pid: 100
flask_1 | [2019-02-23 09:08:45 +0000] [104] [INFO] Booting worker with pid: 104
flask_1 | [2019-02-23 09:08:46 +0000] [108] [INFO] Booting worker with pid: 108
flask_1 | [2019-02-23 09:08:47 +0000] [112] [INFO] Booting worker with pid: 112
flask_1 | [2019-02-23 09:08:48 +0000] [116] [INFO] Booting worker with pid: 116
flask_1 | [2019-02-23 09:08:49 +0000] [120] [INFO] Booting worker with pid: 120
flask_1 | [2019-02-23 09:08:50 +0000] [124] [INFO] Booting worker with pid: 124
flask_1 | [2019-02-23 09:08:52 +0000] [128] [INFO] Booting worker with pid: 128
Aquí está docker-compose.yml
:
version: '3'
services:
flask:
build: .
command: gunicorn -b 0.0.0.0:5000 hello:app --reload
environment:
- FLASK_APP=hello.py
- FLASK_DEBUG=1
- PYTHONUNBUFFERED=True
ports:
- "5000:5000"
volumes:
- ./:/root
¿Qué imagen de Docker usa?
@benoitc
[ec2-user@ip-172-31-85-181 web-services-course]$ docker --version
Docker version 18.06.1-ce, build e68fc7a215d7133c34aa18e3b72b4a21fd0c6136
[ec2-user@ip-172-31-85-181 web-services-course]$ docker-compose --version
docker-compose version 1.23.2, build 1110ad01
Aquí están los enlaces para:
Descubrí que podría deberse a la falta de memoria. la aplicación necesita más memoria de la que está disponible.
pero es solo una suposición
Solo como información: había observado exactamente este comportamiento cuando tengo una configuración de gunicorn para 3 trabajadores, pero implementé el código en una máquina virtual con una CPU de un solo núcleo. Luego, cambio el entorno para usar 2 núcleos, y obviamente el problema desapareció
¿Por qué 'Trabajador sale' solo en el nivel INFO? ¿Por qué saldría un trabajador excepto como resultado de un error? Me tomó mucho tiempo darme cuenta de que el asesino de OOM del sistema estaba matando mis subprocesos de trabajo, sin nada en los registros excepto, como lo informaron algunos otros anteriormente, 'Arrancando trabajador con pid' de vez en cuando.
@HughWarrington porque la salida de un trabajador no es necesariamente un error. Los trabajadores pueden ser despedidos por señales o por opciones como --max-requests
.
@HughWarrington , probablemente podríamos agregar el registro en el árbitro para cuando un trabajador sale con un código de salida anormal.
Puede abrir un boleto para eso o contribuir con un PR que agregue este código al método reap_workers
.
Tuve el mismo problema y la solución fue aumentar el tamaño de la memoria del pod.
Tenía el mismo problema al ejecutar Gunicorn en Docker con un modelo de espacio grande, seguía reiniciando a los trabajadores sin ningún mensaje de error. La solución es aumentar la memoria del contenedor Docker.
Acabo de encontrar este problema hoy en el último gunicorn (19.9.0) con trabajadores gevent (1.4.0) que se ejecutan en Kubernetes. La aplicación es una aplicación de Falcon y la imagen de Docker es la imagen oficial de Python con la etiqueta 3.7.3
.
[2019-07-05 00:07:42 +0000] [8] [INFO] Starting gunicorn 19.9.0
[2019-07-05 00:07:42 +0000] [8] [INFO] Listening at: http://0.0.0.0:5000 (8)
[2019-07-05 00:07:42 +0000] [8] [INFO] Using worker: gevent
[2019-07-05 00:07:43 +0000] [35] [INFO] Booting worker with pid: 35
[2019-07-05 00:07:43 +0000] [36] [INFO] Booting worker with pid: 36
[2019-07-05 00:07:43 +0000] [37] [INFO] Booting worker with pid: 37
[2019-07-05 00:07:43 +0000] [38] [INFO] Booting worker with pid: 38
[2019-07-05 00:07:43 +0000] [41] [INFO] Booting worker with pid: 41
[2019-07-05 00:07:43 +0000] [43] [INFO] Booting worker with pid: 43
[2019-07-05 00:07:43 +0000] [45] [INFO] Booting worker with pid: 45
[2019-07-05 00:07:43 +0000] [49] [INFO] Booting worker with pid: 49
[2019-07-05 00:07:43 +0000] [47] [INFO] Booting worker with pid: 47
[2019-07-05 00:07:49 +0000] [53] [INFO] Booting worker with pid: 53
[2019-07-05 00:07:50 +0000] [54] [INFO] Booting worker with pid: 54
[2019-07-05 00:07:53 +0000] [57] [INFO] Booting worker with pid: 57
[...]
El pod tenía la siguiente configuración de recursos:
resources:
requests:
cpu: 250m
memory: 256Mi
limits:
cpu: 500m
memory: 512Mi
Duplicar todo solucionó el problema.
Una cosa interesante que notamos fue que cuando miramos dmesg
en la máquina host podemos ver que está segfault
-ing en libcrypto
al acceder al servidor usando SSL
La memoria no parece ser un problema para mí porque no estoy cargando ningún modelo grande en la memoria. Los trabajadores siguen fallando y no veo ningún mensaje de error. ¿Hay alguna solución para esto?
mismo problema para mí, ¿alguna idea para solucionarlo? python 3.6.3 con gunicorn 19.9.0
@MrKiven, ¿ qué hace tu aplicación? ¿Estás usando cosas como request?
¿Alguien puede proporcionar una forma de reproducir el problema?
Es un administrador de varios componentes que se ejecutan en una tubería. Algunos de ellos pueden iniciar solicitudes HTTP a otros componentes en la misma máquina o en máquinas remotas. Algunos de los módulos de la canalización se pueden ejecutar en paralelo, pero se ejecutan mediante un ThreadPoolExecutor. No usan ningún objeto compartido, solo generan estructuras de datos que luego se agregan en un solo resultado.
Desafortunadamente, no estoy seguro de poder armar un ejemplo mínimo sin exponer el sistema que tenemos.
Las solicitudes hacen muchas cosas inseguras con subprocesos que a veces bifurcan un nuevo proceso. Aconsejaría utilizar otro cliente. ¿Puedes pegar al menos las líneas que estás usando para hacer una solicitud? ¿Está utilizando su función de tiempo de espera?
Uno de ellos podría ser:
try:
resp = requests.post(self._endpoint, json=request_data)
if resp.status_code != 200:
logger.critical("[Error]: status code is {}".format(resp.status_code))
return None
response = resp.json()
return {"intent": response["intent"], "intent_ranking": response["intent_ranking"]}
except ConnectionError as exc:
logger.critical("[Exception] {}".format(str(exc)))
return None
Gracias. Intentaré crear un sencillo a partir de él.
De todos modos, sería genial si alguien nos pudiera enviar un PR que reproduzca el comportamiento, ya sea como un ejemplo o una prueba unitaria para asegurarnos de que realmente estamos arreglando lo correcto.
No estoy seguro de si puede ayudar a alguien, pero tuve el mismo problema mientras ejecutaba una aplicación web de matraz dockerizado y lo resolví actualizando la imagen base de mi archivo docker a python:3.6.9-alpine
Dmesg en el host mostró un error de segmentación en lilibpython3.6m.so.1.0:
[626278.653010] gunicorn[19965]: segfault at 70 ip 00007f6423e7faee sp 00007ffc4e9a2a38 error 4 in libpython3.6m.so.1.0[7f6423d8a000+194000]
Mi imagen de la ventana acoplable se basó en python:3.6-alpine
y estaba haciendo un apk update
que estaba actualizando Python a 3.6.8.
Como dije, cambiar la imagen base a python:3.6.9-alpine
resolvió para mí
Enfrenté el mismo desafío ejecutando un Flask + Docker + Kubernetes. El aumento de los límites de la CPU y la memoria lo resolvió para mí.
A nosotros nos pasó lo mismo. El aumento de los límites de recursos solucionó el problema.
Esto me sucedió de repente en macOS Catalina (no en contenedores).
Lo que me ayudó es:
brew install openssl
~/.zshrc
:export DYLD_LIBRARY_PATH=/usr/local/opt/openssl/lib:$DYLD_LIBRARY_PATH
Estoy teniendo un desafío similar y estaría agradecido si alguien pudiera ayudarme.
Esto es lo que tenía;
" root @ ubuntu-s-1vcpu-1gb-nyc1-01 : ~ # sudo systemctl status gunicorn.service ● gunicorn.service - demonio gunicorn Cargado: cargado (/etc/systemd/system/gunicorn.service; deshabilitado; preset del proveedor: habilitado) Activo: activo (en ejecución) desde Mon 2020-02-24 07:48:04 UTC; hace 44min PID principal: 4846 (gunicorn) Tareas: 4 (límite: 1151) CGroup: /system.slice/gunicorn.service ├ ─4846 / home / bright / djangoprojectdir / djangoprojectenv / bin / python / home / bright / djangoprojectdir / djangoprojectenv / bin / gunicorn - ├─4866 / home / bright / djangoprojectdir / djangoprojectenv / bin / python / home / bright / django / bin / gunicorn - ├─4868 / home / bright / djangoprojectdir / djangoprojectenv / bin / python / home / bright / djangoprojectdir / djangoprojectenv / bin / gunicorn - └─4869 / home / bright / djangoprojectdir / djangoprojectenv / bin / python / home / bright / djangoprojectdir / djangoprojectenv / bin / gunicorn - 24 de febrero 07:48:04 ubuntu-s-1vcpu-1gb-nyc1-01 systemd [1]: Detenido el demonio gunicorn. 24 de febrero 07:48:04 ubuntu-s-1vcpu -1gb-nyc1-01 systemd [1 ]: Inició el demonio gunicorn. 24 de febrero 07:48:05 ubuntu-s-1vcpu-1gb-nyc1-01 gunicorn [4846]: [2020-02-24 07:48:05 +0000] [4846] [INFO] Gunicorn inicial 20.0.4 24 de febrero 07:48:05 ubuntu-s-1vcpu-1gb-nyc1-01 gunicorn [4846]: [2020-02-24 07:48:05 +0000] [4846] [INFO] Escuchando en: unix: / run / gunicorn .soc 24 de febrero 07:48:05 ubuntu-s-1vcpu-1gb-nyc1-01 gunicorn [4846]: [2020-02-24 07:48:05 +0000] [4846] [INFO] Usando worker: sync Feb 24 07:48:05 ubuntu-s-1vcpu-1gb-nyc1-01 gunicorn [4846]: [2020-02-24 07:48:05 +0000] [4866] [INFO] Trabajador de arranque con pid: 4866 24 de febrero 07:48:05 ubuntu-s-1vcpu-1gb-nyc1-01 gunicorn [4846]: [2020-02-24 07:48:05 +0000] [4868] [INFO] Trabajador de arranque con pid: 4868 24 de febrero de 2007 : 48: 05 ubuntu-s-1vcpu-1gb-nyc1-01 gunicorn [4846]: [2020-02-24 07:48:05 +0000] [4869] [INFO] Trabajador de arranque con pid: 4869 24 de febrero 08: 03:41 ubuntu-s-1vcpu-1gb-nyc1-01 gunicorn [4846]: - - [24 / Feb / 2020: 08: 03: 41 +0000] "GET / HTTP / 1.0" 400 26 "-" "Mozilla /5.0 (Wi líneas 1-20 / 20 (FIN) "¿Alguien puede ayudarme a arreglar eso?
@BrightNana, ¿puedes intentar dar un dmesg
y ver si tienes algún error de gunicorn?
dmesg | grep gunicorn
podría ayudar a filtrar los otros errores
Hola,
Tengo el mismo error en debian 9 cuando quiero proporcionar gunicorn como un servicio systemd. Si lo inicio desde la CLI, gunicorn se ejecuta sin errores.
Extracto de dmesg | grep gunicorn
:
Extracto de journalctl
:
Mär 12 07:01:06 build-server gunicorn[828]: [2020-03-12 07:01:06 +0100] [1054] [INFO] Booting worker with pid: 1054 Mär 12 07:01:06 build-server gunicorn[828]: [2020-03-12 07:01:06 +0100] [1057] [INFO] Booting worker with pid: 1057 Mär 12 07:01:06 build-server gunicorn[828]: [2020-03-12 07:01:06 +0100] [1060] [INFO] Booting worker with pid: 1060 Mär 12 07:01:07 build-server gunicorn[828]: [2020-03-12 07:01:07 +0100] [1064] [INFO] Booting worker with pid: 1064 Mär 12 07:01:07 build-server gunicorn[828]: [2020-03-12 07:01:07 +0100] [1067] [INFO] Booting worker with pid: 1067 Mär 12 07:01:07 build-server gunicorn[828]: [2020-03-12 07:01:07 +0100] [1070] [INFO] Booting worker with pid: 1070 Mär 12 07:01:07 build-server gunicorn[828]: [2020-03-12 07:01:07 +0100] [1073] [INFO] Booting worker with pid: 1073 Mär 12 07:01:07 build-server gunicorn[828]: [2020-03-12 07:01:07 +0100] [1076] [INFO] Booting worker with pid: 1076 Mär 12 07:01:08 build-server gunicorn[828]: [2020-03-12 07:01:08 +0100] [1079] [INFO] Booting worker with pid: 1079 Mär 12 07:01:08 build-server gunicorn[828]: [2020-03-12 07:01:08 +0100] [1082] [INFO] Booting worker with pid: 1082 Mär 12 07:01:08 build-server gunicorn[828]: [2020-03-12 07:01:08 +0100] [1085] [INFO] Booting worker with pid: 1085 Mär 12 07:01:08 build-server gunicorn[828]: [2020-03-12 07:01:08 +0100] [1088] [INFO] Booting worker with pid: 1088 Mär 12 07:01:08 build-server gunicorn[828]: [2020-03-12 07:01:08 +0100] [1091] [INFO] Booting worker with pid: 1091 Mär 12 07:01:09 build-server gunicorn[828]: [2020-03-12 07:01:09 +0100] [1094] [INFO] Booting worker with pid: 1094
Extracto de systemctl status
:
● api.service - API Server for BuildingChallenge served with Gunicorn Loaded: loaded (/etc/systemd/system/api.service; disabled; vendor preset: enabled) Active: active (running) since Thu 2020-03-12 08:26:01 CET; 22min ago Main PID: 8150 (gunicorn) Tasks: 3 (limit: 4915) Memory: 37.7M (high: 100.0M max: 500.0M) CGroup: /system.slice/api.service ├─ 8150 /opt/api/venv/bin/python /opt/api/venv/bin/gunicorn --bind unix:api.sock wsgi:app ├─28936 /opt/api/venv/bin/python /opt/api/venv/bin/gunicorn --bind unix:api.sock wsgi:app └─28938 /usr/bin/python3 -Es /usr/bin/lsb_release -a Mär 12 08:48:01 build-server gunicorn[8150]: [2020-03-12 08:48:01 +0100] [28909] [INFO] Booting worker with pid: 28909 Mär 12 08:48:01 build-server gunicorn[8150]: [2020-03-12 08:48:01 +0100] [28912] [INFO] Booting worker with pid: 28912 Mär 12 08:48:01 build-server gunicorn[8150]: [2020-03-12 08:48:01 +0100] [28915] [INFO] Booting worker with pid: 28915 Mär 12 08:48:01 build-server gunicorn[8150]: [2020-03-12 08:48:01 +0100] [28918] [INFO] Booting worker with pid: 28918 Mär 12 08:48:01 build-server gunicorn[8150]: [2020-03-12 08:48:01 +0100] [28921] [INFO] Booting worker with pid: 28921 Mär 12 08:48:01 build-server gunicorn[8150]: [2020-03-12 08:48:01 +0100] [28924] [INFO] Booting worker with pid: 28924 Mär 12 08:48:02 build-server gunicorn[8150]: [2020-03-12 08:48:02 +0100] [28927] [INFO] Booting worker with pid: 28927 Mär 12 08:48:02 build-server gunicorn[8150]: [2020-03-12 08:48:02 +0100] [28930] [INFO] Booting worker with pid: 28930 Mär 12 08:48:02 build-server gunicorn[8150]: [2020-03-12 08:48:02 +0100] [28933] [INFO] Booting worker with pid: 28933 Mär 12 08:48:02 build-server gunicorn[8150]: [2020-03-12 08:48:02 +0100] [28936] [INFO] Booting worker with pid: 28936
Gracias por tu ayuda.
Puse un PR que podría ayudar a depurar este tipo de situaciones. ¿Alguien puede echar un vistazo?
https://github.com/benoitc/gunicorn/pull/2315
Tuve el mismo problema con una aplicación Flask que se ejecuta dentro de Docker. Los trabajadores se reiniciaban infinitamente con un ID de proceso cada vez mayor.
El problema estaba relacionado con la memoria para mí, cuando aumenté la memoria permitida para Docker, los trabajadores se generaron de manera efectiva.
@tilgovi , no me importa si te gustaría incorporar mis cambios en tus relaciones públicas desde que llegaste primero. Esto cubrirá a los trabajadores que mueren a través de señales.
@mildebrandt Echaré un vistazo, ¡gracias!
También veo este comportamiento de repente, usando Gunicorn (20.0.4) + Gevent (1.5.0) + Flask dentro de un contenedor Docker.
[ 328.699160] gunicorn[5151]: segfault at 78 ip 00007fc1113c16be sp 00007ffce50452a0 error 4 in _greenlet.cpython-37m-x86_64-linux-gnu.so[7fc11138d000+3e000]
En mi caso, como puede ver, el segfault está siendo causado por gevent. Lo extraño es que este contenedor funcionó bien hace 5 días, y ninguno de los cambios de código desde entonces cambió ninguna versión de ninguna de las bibliotecas, y todas están configuradas para versiones específicas. Eliminé flask-mail como dependencia, lo que puede haber alterado ligeramente las versiones de otras dependencias.
La actualización de gevent == 1.5.0 a gevent == 20.9.0 resolvió el problema por mí.
@ifiddes , es probable que su problema no esté relacionado. Está viendo un problema de compatibilidad ABI entre las versiones antiguas de gevent con la versión más reciente de greenlet. Ver https://github.com/python-greenlet/greenlet/issues/178
Ah, gracias @jamadden. Esta publicación fue todo lo que pude encontrar al buscar un desove infinito de trabajadores de arranque, pero ese problema y el momento en que se produjo se ajustan a mi problema.
Tuve un error similar con una nueva máquina AWS con Ubuntu 20.04 Server y con el mismo código que funciona en producción.
La máquina se configuró utilizando Ansible como las otras máquinas de producción.
[2020-10-15 15:11:49 +0000] [18068] [DEBUG] Current configuration:
config: None
bind: ['127.0.0.1:8000']
backlog: 2048
workers: 1
worker_class: uvicorn.workers.UvicornWorker
threads: 1
worker_connections: 1000
max_requests: 0
max_requests_jitter: 0
timeout: 30
graceful_timeout: 30
keepalive: 2
limit_request_line: 4094
limit_request_fields: 100
limit_request_field_size: 8190
reload: False
reload_engine: auto
reload_extra_files: []
spew: False
check_config: False
preload_app: False
sendfile: None
reuse_port: False
chdir: /var/www/realistico/app
daemon: False
raw_env: []
pidfile: None
worker_tmp_dir: None
user: 1001
group: 1001
umask: 0
initgroups: False
tmp_upload_dir: None
secure_scheme_headers: {'X-FORWARDED-PROTOCOL': 'ssl', 'X-FORWARDED-PROTO': 'https', 'X-FORWARDED-SSL': 'on'}
forwarded_allow_ips: ['127.0.0.1']
accesslog: /var/www/realistico/logs/gunicorn/access.log
disable_redirect_access_to_syslog: False
access_log_format: %(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s"
errorlog: /var/www/realistico/logs/gunicorn/error.log
loglevel: debug
capture_output: False
logger_class: gunicorn.glogging.Logger
logconfig: None
logconfig_dict: {}
syslog_addr: udp://localhost:514
syslog: False
syslog_prefix: None
syslog_facility: user
enable_stdio_inheritance: False
statsd_host: None
dogstatsd_tags:
statsd_prefix:
proc_name: None
default_proc_name: realistico.asgi:application
pythonpath: None
paste: None
on_starting: <function OnStarting.on_starting at 0x7f7ba5fdd550>
on_reload: <function OnReload.on_reload at 0x7f7ba5fdd670>
when_ready: <function WhenReady.when_ready at 0x7f7ba5fdd790>
pre_fork: <function Prefork.pre_fork at 0x7f7ba5fdd8b0>
post_fork: <function Postfork.post_fork at 0x7f7ba5fdd9d0>
post_worker_init: <function PostWorkerInit.post_worker_init at 0x7f7ba5fddaf0>
worker_int: <function WorkerInt.worker_int at 0x7f7ba5fddc10>
worker_abort: <function WorkerAbort.worker_abort at 0x7f7ba5fddd30>
pre_exec: <function PreExec.pre_exec at 0x7f7ba5fdde50>
pre_request: <function PreRequest.pre_request at 0x7f7ba5fddf70>
post_request: <function PostRequest.post_request at 0x7f7ba5f6e040>
child_exit: <function ChildExit.child_exit at 0x7f7ba5f6e160>
worker_exit: <function WorkerExit.worker_exit at 0x7f7ba5f6e280>
nworkers_changed: <function NumWorkersChanged.nworkers_changed at 0x7f7ba5f6e3a0>
on_exit: <function OnExit.on_exit at 0x7f7ba5f6e4c0>
proxy_protocol: False
proxy_allow_ips: ['127.0.0.1']
keyfile: None
certfile: None
ssl_version: 2
cert_reqs: 0
ca_certs: None
suppress_ragged_eofs: True
do_handshake_on_connect: False
ciphers: None
raw_paste_global_conf: []
strip_header_spaces: False
[2020-10-15 15:11:49 +0000] [18068] [INFO] Starting gunicorn 20.0.4
[2020-10-15 15:11:49 +0000] [18068] [DEBUG] Arbiter booted
[2020-10-15 15:11:49 +0000] [18068] [INFO] Listening at: unix:/run/gunicorn.sock (18068)
[2020-10-15 15:11:49 +0000] [18068] [INFO] Using worker: uvicorn.workers.UvicornWorker
[2020-10-15 15:11:49 +0000] [18080] [INFO] Booting worker with pid: 18080
[2020-10-15 15:11:49 +0000] [18068] [DEBUG] 1 workers
[2020-10-15 15:11:51 +0000] [18083] [INFO] Booting worker with pid: 18083
[2020-10-15 15:11:53 +0000] [18086] [INFO] Booting worker with pid: 18086
...
[2020-10-15 15:12:09 +0000] [18120] [INFO] Booting worker with pid: 18120
[2020-10-15 15:12:11 +0000] [18123] [INFO] Booting worker with pid: 18123
Después de mucho tiempo perdido tratando de resolver este problema sin éxito (y sin ningún error en los registros), lo intenté con este Hola mundo y encontré este error:
ModuleNotFoundError: No module named 'httptools'
Después de instalar httptools
la aplicación Hello world funciona bien e, inesperadamente, también funciona mi aplicación.
No tengo idea de por qué no se registró el error o por qué esta biblioteca se instaló en las otras máquinas pero no en la nueva, pero esto solucionó el problema por mí.
Si esto sucediera recientemente y derribara el nodo de kubernetes en el que estaba consumiendo toda la CPU. Gracias a la pista sobre dmesg
, finalmente encontré un error:
[225027.348869] traps: python[44796] general protection ip:7f8bd8f8f8b0 sp:7ffc21a0b370 error:0 in libpython3.7m.so.1.0[7f8bd8dca000+2d9000]
Al final, mi problema fue otra instancia de https://github.com/python-greenlet/greenlet/issues/178 y se resolvió actualizando gunicorn, gevent y greenlet a la última versión.
Dado que estos tipos de excepciones no crean registros de Python, no se pueden detectar, devuelven el código de salida 0 y pueden bloquear la máquina cuando ocurren, son bastante difíciles de administrar.
Propongo que Gunicorn detecte un bucle de choque rápido de esta naturaleza y
quizás max_consecutive_startup_crashes
con el valor predeterminado num_workers * 10?
Rastreemos la solicitud de función de bucle de bloqueo en # 2504. También tenemos el RP para iniciar sesión adicional en # 2315. Cerraré este problema ya que parece que todos han depurado sus problemas y ahora tenemos algunas solicitudes de funciones y mejoras para ayudar a otros en el futuro. ¡Gracias a todos!
Comentario más útil
Solo una actualización, el problema para mí era en realidad un error de memoria y se solucionó cuando se solucionó el problema de memoria.