Gunicorn: "Booting worker" boucle à l'infini malgré aucun signal de sortie

Créé le 11 déc. 2017  ·  65Commentaires  ·  Source: benoitc/gunicorn

J'essaie de configurer gunicorn sur Docker. Cela fonctionne bien localement et l'image de production est exactement la même que l'image locale, mais j'obtiens ce comportement étrange sur le moteur Docker de production :

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.

Il semble que gunicorn démarre les travailleurs toutes les 4 à 5 secondes, malgré l'absence de messages d'erreur ou de signaux de sortie apparents. Ce comportement continue indéfiniment jusqu'à ce qu'il soit terminé.

Est-il possible qu'un travailleur puisse quitter sans rien enregistrer sur stderr/stdout, ou que l'arbitre génère des travailleurs à l'infini ?

Puisqu'il s'agit de la même image docker, ils exécutent exactement le même code, sur exactement la même architecture, donc je ne comprends vraiment pas ce que cela pourrait être (bug ?). Toute aide grandement appréciée!

Improvement help wanted

Commentaire le plus utile

Juste une mise à jour, le problème pour moi était en fait une erreur de mémoire et a été corrigé lorsque le problème de mémoire a été résolu.

Tous les 65 commentaires

ssh -ing dans le conteneur Docker m'a amené à trouver cette erreur :

Illegal instruction (core dumped)

Peut-être que le gunicorn devrait faire apparaître des erreurs comme celle-ci au lieu de les avaler, ou les gérer différemment ? Je ne sais pas, j'ai juste pensé que je soulèverais cette question car cela pourrait aider quelqu'un d'autre !

Merci d'avoir signalé le problème !

Si vous pouvez savoir où cela se produit, ce serait très utile.

Peut-être pouvons-nous ajouter la journalisation lorsque les travailleurs quittent. Habituellement, le travailleur lui-même se connecte, mais s'il est tué très brusquement, il ne le fera pas.

Pas de soucis!

Il semble y avoir un problème avec Spacy que je viens d'ajouter à ce fil : https://github.com/explosion/spaCy/issues/1589

Quoi qu'il en soit, cela provoque un SIGILL comme strace confirme :

--- SIGILL {si_signo=SIGILL, si_code=ILL_ILLOPN, si_addr=0x7ff48bbe6cea} ---
+++ killed by SIGILL (core dumped) +++
Illegal instruction (core dumped)

Je suppose que ce serait bien si gunicorn pouvait identifier cela et enregistrer une erreur plutôt que de redémarrer fantômement le travailleur, mais je sais très peu de choses sur le fonctionnement des codes de sortie !

Certains codes de sortie ont certainement des significations spéciales et nous pourrions probablement les enregistrer.
http://tldp.org/LDP/abs/html/exitcodes.html

Ça a l'air bien! De plus, si le code de sortie n'est pas un code de sortie réservé (comme dans ce cas), ce serait cool si cela pouvait être enregistré (sans explication) afin qu'il soit évident que le travailleur termine effectivement 🙂

J'ai un problème similaire, gunicorn démarre toujours un nouveau travailleur lorsque je fais une demande http. Je ne reçois aucune réponse, cela redémarre toujours le nouveau travailleur. Tracer le journal de deux requêtes 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

Je suis confronté au même problème, gunicorn démarre en quelques secondes pour le type de travailleur sync . Définir le délai d'expiration du travailleur sur 900 n'aide pas.

Dans ma charge avant action, je télécharge des données depuis AWS S3. Il faut environ 1min 10 sec pour télécharger les différents fichiers.

@sara-02 quelle est ta ligne de commande pour lancer gunicorn ?

@benoitc gunicorn --pythonpath /src -b 0.0.0.0:$SERVICE_PORT --workers=1 -k sync -t $SERVICE_TIMEOUT flask_endpoint:app
Présenter ici

@sara-02 Merci.

Les anciens travailleurs sortent-ils vraiment ou sont-ils maintenus en ligne et de nouveaux travailleurs sont-ils générés ? Que montre également le journal de débogage ?

Les journaux sont mélangés avec les journaux botocore, mais c'est quelque chose comme ça

[INFO] Booting worker with pid:  a
[INFO] Booting worker with pid:  b
[INFO] Booting worker with pid:  c

mais l'ouvrier est-il tué ? que renvoie la commande ps ax|grep gunicorn ?

@benoitc
screenshot from 2018-07-05 19-14-00

Une question cependant, pourquoi voyons-nous 2 processus gunicorn , lorsque la limite de travail est définie sur 1 ? Y a-t-il un maître et un ouvrier ?

Il y a 1 processus arbitre (maître) et N processus ouvriers vous :)

Donc, vous exécutez la commande à chaque démarrage d'un travailleur, n'est-ce pas ? Si c'est le cas, il semble que le travailleur plus âgé est tué, un nouveau est généré. Je vais me renseigner.

@sara-02 une dernière chose, cela se passe également dans docker?

@benoitc sur docker-compose cela fonctionne comme prévu, mais lorsque je mets le même code sur Openshift , je vois cette erreur. L'augmentation de la mémoire requise a été corrigée, mais lorsque j'exécute l'application via docker-compose elle utilise moins de limited mémoire.

Juste une mise à jour, le problème pour moi était en fait une erreur de mémoire et a été corrigé lorsque le problème de mémoire a été résolu.

@benoitc
Je suis confronté au même problème en essayant de faire apparaître 5 travailleurs gunicorn dans docker.
@sara-02
Comment avez-vous identifié la cause d'une erreur de mémoire ?

image

@gulshan-gaurav 2 choses m'ont aidé :
J'ai augmenté la mémoire attribuée à mon Pod et j'ai arrêté de planter. Deuxièmement, nous avons vérifié nos journaux Openshift Zabbix.

@sara-02
Même sur mon pod de staging, les fichiers + modèles que je charge en mémoire s'élèvent à 50 Mo, donc 2 Go de mémoire devraient suffire pour 5 travailleurs.

@gulshan-gaurav quel problème rencontrez-vous ? Avoir 5 processus là-bas semble bien ....

J'ai eu le même problème. Je n'ai pas localisé le problème exact, mais il a été résolu une fois que je suis passé de python 3.5 à 3.6.

Je suis confronté au même problème dans un conteneur Docker. Gunicorn continue à botter un nouveau travailleur chaque fois que j'appelle un point de terminaison qui provoque l'échec, mais aucune exception ou erreur n'est générée dans les fichiers journaux de Gunicorn. Les choses que je choisis d'imprimer sont enregistrées, puis soudain, le fichier journal dit simplement "Booting worker with pid..."

Une étape qui a aidé a été d'ajouter la variable d'environnement PYTHONUNBUFFERED. Avant cela, même les déclarations d'impression disparaissaient et ne seraient pas enregistrées dans les journaux de Gunicorn.

2 autres points de terminaison de l'application fonctionnent correctement.

Je lance Gunicorn avec : gunicorn run:app -b localhost:5000 --enable-stdio-inheritance --error-logfile /var/log/gunicorn/error.log --access-logfile /var/log/gunicorn/access. log --capture-output --débogage au niveau du journal

Exécutant déjà Python 3.6 et vérifié avec top que la mémoire ne semble pas être un problème.

EDIT : On dirait que c'était un problème de Python et non la faute d'un Gunicorn. Certaines divergences de version provoquaient la mort de Python sans aucune trace lors de l'exécution d'une certaine opération.

Je suis confronté à un problème similaire où le nœud de travail continue à proposer
Booting worker with pid: 17636 . Je ne sais pas si cela tue le nœud de travail précédent ou si le nœud de travail précédent existe toujours. Mais le nombre de travailleurs mentionnés dans les arguments de la ligne de commande gunicorn n'est que de 3 - -workers=3 . J'utilise aussi python version 3.7

J'ai eu un décalage de dépendance scikit-learn, mais même après avoir résolu ce problème, je reçois toujours les mêmes travailleurs infinis à venir. quel type de divergences de version python dois-je rechercher et comment les identifier ?

Je suis confronté au même problème dans OpenShift.

image

Comme vous pouvez le voir sur l'image, j'utilise 6 ouvriers (j'essayais avec 3).
J'ai augmenté la mémoire du pod et cela n'a pas fonctionné.

BuildConfig :

image

Une idée?

Merci

exécutez-vous cela dans aws derrière elb? J'ai résolu ce problème en mettant nginx ingress entre elb et gunicorn

Avoir le même problème.

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

Voici 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

quelle image de docker utilise-t-il ?

@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

Voici les liens pour :

compris que cela pouvait être causé par un manque de mémoire. l'application a besoin de plus de mémoire que ce qui est disponible.
mais ce n'est qu'une supposition

Juste pour information : j'avais observé exactement ce comportement lorsque j'avais une conf gunicorn à 3 travailleurs, mais j'ai déployé le code dans une machine virtuelle avec un seul processeur core. Ensuite, je change d'environnement pour utiliser 2 cœurs, et évidemment le problème a disparu

Pourquoi « Worker exiting » n'est-il qu'au niveau INFO – pourquoi un worker sortirait-il, sauf à la suite d'une erreur ? Il m'a fallu beaucoup de temps pour comprendre que mes threads de travail étaient tués par le tueur OOM du système, sans rien dans les journaux sauf, comme indiqué par d'autres ci-dessus, "Démarrer le travailleur avec pid" de temps en temps.

@HughWarrington car la sortie d'un travailleur n'est pas nécessairement une erreur. Les travailleurs peuvent être terminés par des signaux ou par des options comme --max-requests .

@HughWarrington, nous pourrions probablement ajouter la connexion à l'arbitre lorsqu'un travailleur quitte avec un code de sortie anormal.

Vous pouvez ouvrir un ticket pour cela ou contribuer à un PR qui ajoute ce code à la méthode reap_workers .

J'ai eu le même problème, et la solution était d'augmenter la taille de la mémoire du pod.

A eu le même problème lors de l'exécution de Gunicorn sur Docker avec un grand modèle spaCy, il a continué à redémarrer les travailleurs sans aucun message d'erreur. La solution consiste à augmenter la mémoire du conteneur Docker.

Je viens de rencontrer ce problème aujourd'hui sur le dernier (19.9.0) gunicorn avec les travailleurs gevent (1.4.0) s'exécutant sur Kubernetes. L'application est une application Falcon et l'image Docker est l' image Python officielle avec la balise 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
[...]

Le pod avait les paramètres de ressources suivants :

resources:
  requests:
    cpu: 250m
    memory: 256Mi
  limits:
    cpu: 500m
    memory: 512Mi

Tout doubler a résolu le problème.

Une chose intéressante que nous avons remarquée est que lorsque nous regardons dmesg sur la machine hôte, nous pouvons voir qu'il s'agit de segfault -ing à libcrypto lors de l'accès au serveur en utilisant SSL

La mémoire ne semble pas être un problème pour moi car je ne charge aucun gros modèle en mémoire. Les travailleurs continuent de planter et je ne vois aucun message d'erreur. Existe-t-il un correctif pour cela?

image

même problème pour moi, une idée à résoudre ? python 3.6.3 avec gunicorn 19.9.0

@MrKiven, que fait votre application ? utilisez-vous des trucs comme request?

quelqu'un peut-il fournir un moyen de reproduire le problème?

C'est un gestionnaire de plusieurs composants qui sont exécutés dans un pipeline. Certains d'entre eux peuvent lancer des requêtes HTTP vers d'autres composants sur la même machine ou sur des machines distantes. Certains des modules du pipeline peuvent être exécutés en parallèle mais ils sont exécutés à l'aide d'un ThreadPoolExecutor. Ils n'utilisent pas d'objets partagés mais ne génèrent que des structures de données qui sont ensuite agrégées en une seule résultante.

Malheureusement, je ne sais pas si je peux rassembler un exemple minimal sans exposer le système que nous avons.

request fait beaucoup de choses dangereuses avec les threads qui forcent parfois un nouveau processus. Je conseillerais d'utiliser un autre client. pouvez-vous coller au moins les lignes que vous utilisez pour faire une requête ? Utilisez-vous sa fonction de délai d'attente ?

L'un d'eux pourrait être :

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

Merci. Je vais essayer de créer un simple à partir de celui-ci.

Ce serait cool de toute façon si quelqu'un pouvait nous envoyer un pr qui reproduisait le comportement soit à titre d'exemple ou de test unitaire afin que nous nous assurons que nous réparons réellement la bonne chose.

Je ne sais pas si cela peut aider quelqu'un, mais j'ai eu le même problème lors de l'exécution d'une application Web de flacons dockerisés et je l'ai résolu en mettant à jour l'image de base de mon fichier docker à python:3.6.9-alpine

Dmesg sur l'hôte a montré une erreur de segmentation sur 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]

Mon image docker était basée sur python:3.6-alpine et faisait un apk update qui mettait à jour python vers 3.6.8.

Comme dit, changer l'image de base en python:3.6.9-alpine résolu pour moi

J'ai été confronté au même défi en exécutant un Flask + Docker + Kubernetes. L'augmentation des limites du processeur et de la mémoire l'a résolu pour moi.

La même chose nous est arrivée. L'augmentation des limites de ressources a résolu le problème.

Cela m'est soudainement arrivé sur macOS Catalina (non conteneurisé).

Ce qui m'a aidé c'est :

  1. Installation d'openssl :
brew install openssl
  1. Exécuter et ajouter ceci à mon ~/.zshrc :
export DYLD_LIBRARY_PATH=/usr/local/opt/openssl/lib:$DYLD_LIBRARY_PATH

Source : https://stackoverflow.com/a/58445755/5811984

J'ai un défi similaire et je serais reconnaissant si quelqu'un peut m'aider.
C'est ce que j'avais ;

" root@ubuntu-s-1vcpu-1gb-nyc1-01 :~# sudo systemctl status gunicorn.service ● gunicorn.service - démon gunicorn Chargé : chargé (/etc/systemd/system/gunicorn.service ; désactivé ; préréglage du fournisseur : activé) Actif : actif (en cours d'exécution) depuis le lun. 2020-02-24 07:48:04 UTC ; il y a 44 min PID principal : 4846 (gunicorn) Tâches : 4 (limite : 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/djangoprojectdir/djangoprojectdir/djangoprojectdir/djangoprojectdir /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 février 07:48:04 ubuntu-s-1vcpu-1gb-nyc1-01 systemd[1] : Démon gunicorn arrêté. 24 février 07:48:04 ubuntu-s-1vcpu -1gb-nyc1-01 systemd[1 ] : Lancement du démon gunicorn. 24 février 07:48:05 ubuntu-s-1vcpu-1gb-nyc1-01 gunicorn[4846]: [2020-02-24 07:48:05 +0000] [4846] [INFO] Démarrage de gunicorn 20.0.4 24 février 07:48:05 ubuntu-s-1vcpu-1gb-nyc1-01 gunicorn[4846]: [2020-02-24 07:48:05 +0000] [4846] [INFO] Écoute sur : unix:/run/gunicorn .soc 24 février 07:48:05 ubuntu-s-1vcpu-1gb-nyc1-01 gunicorn[4846] : [2020-02-24 07:48:05 +0000] [4846] [INFO] Utilisation du travailleur : sync février 24 07:48:05 ubuntu-s-1vcpu-1gb-nyc1-01 gunicorn[4846]: [2020-02-24 07:48:05 +0000] [4866] [INFO] Travailleur de démarrage avec pid: 4866 24 février 07:48:05 ubuntu-s-1vcpu-1gb-nyc1-01 gunicorn[4846]: [2020-02-24 07:48:05 +0000] [4868] [INFO] Travailleur de démarrage avec pid: 4868 24 février 07 :48:05 ubuntu-s-1vcpu-1gb-nyc1-01 gunicorn[4846]: [2020-02-24 07:48:05 +0000] [4869] [INFO] Travailleur de démarrage avec pid : 4869 24 février 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 lines 1-20/20 (END)" Quelqu'un peut-il m'aider à résoudre ce problème ?

@BrightNana pouvez-vous essayer de donner un dmesg et voir si vous avez des erreurs gunicorn ?
dmesg | grep gunicorn pourrait aider à filtrer les autres erreurs

Bonjour,
j'ai le même bogue dans debian 9 lorsque je veux fournir gunicorn en tant que service systemd. Si je le démarre à partir de la CLI, gunicorn s'exécute sans erreur.

Extrait de dmesg | grep gunicorn :

Extrait 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
Extrait 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

Merci de votre aide.

J'ai mis en place un PR qui pourrait aider à déboguer ce genre de situations. Quelqu'un peut-il jeter un oeil?
https://github.com/benoitc/gunicorn/pull/2315

J'ai eu le même problème avec une application Flask exécutée dans Docker. Les travailleurs redémarraient à l'infini avec un ID de processus croissant.
image

Le problème était lié à la mémoire pour moi, lorsque j'ai augmenté la mémoire autorisée pour Docker, les travailleurs sont apparus efficacement.
image

@tilgovi , cela ne me dérange pas si vous souhaitez intégrer mes modifications dans vos relations publiques depuis que vous y êtes arrivé en premier. Cela couvrira les travailleurs tués par des signaux.

@mildebrandt je vais regarder, merci !

Je constate également ce comportement soudainement, en utilisant Gunicorn (20.0.4) + Gevent (1.5.0) + Flask à l'intérieur d'un conteneur 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]

Dans mon cas, comme vous pouvez le voir, la faute de segmentation est causée par gevent. Ce qui est étrange, c'est que ce conteneur a bien fonctionné il y a 5 jours, et aucun des changements de code depuis lors n'a modifié les versions de l'une des bibliothèques, et toutes sont définies sur des versions spécifiques. J'ai supprimé flask-mail en tant que dépendance, ce qui a peut-être légèrement modifié les versions d'autres dépendances.

La mise à jour de gevent==1.5.0 vers gevent==20.9.0 a résolu le problème pour moi.

@ifiddes votre problème n'est probablement pas lié. Vous constatez un problème de compatibilité ABI entre les anciennes versions de gevent avec la version la plus récente du greenlet. Voir https://github.com/python-greenlet/greenlet/issues/178

Ah, merci @jamadden. Ce message était tout ce que j'ai pu trouver lors de la recherche d'une génération infinie de travailleurs de démarrage, mais ce problème et le moment de ce problème correspondent à mon problème.

J'ai eu une erreur similaire avec une nouvelle machine AWS avec Ubuntu 20.04 Server et avec le même code qui fonctionne en production.

La machine a été configurée à l'aide d' Ansible comme les autres machines de production.

[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

Après beaucoup de temps perdu à essayer de résoudre ce problème sans succès (et sans aucune erreur sur les journaux), j'ai essayé avec ce Hello world et j'ai trouvé cette erreur :

ModuleNotFoundError: No module named 'httptools'

Après avoir installé httptools l'application Hello world fonctionne correctement et, de manière inattendue, fonctionne également avec mon application.

Je ne sais pas pourquoi l'erreur n'a pas été enregistrée ou pourquoi cette bibliothèque a été installée sur les autres machines mais pas sur la nouvelle, mais cela résout le problème pour moi.

Si cela s'était produit récemment et que vous détruisiez le nœud kubernetes sur lequel il se trouvait en consommant tout le processeur. Grâce à l'indice sur dmesg j'ai finalement trouvé une erreur :

[225027.348869] traps: python[44796] general protection ip:7f8bd8f8f8b0 sp:7ffc21a0b370 error:0 in libpython3.7m.so.1.0[7f8bd8dca000+2d9000]

En fin de compte, mon problème était une autre instance de https://github.com/python-greenlet/greenlet/issues/178 et a été résolu en mettant à jour gunicorn, gevent et greenlet vers la dernière version.

Étant donné que ces types d'exceptions ne créent pas de journaux python, ne peuvent pas être interceptés, renvoient le code de sortie 0 et peuvent bloquer la machine lorsqu'ils se produisent, ils sont assez difficiles à gérer.

Je propose que gunicorn détecte les boucles rapides de cette nature et

peut-être max_consecutive_startup_crashes avec par défaut num_workers * 10 ?

Suivons la demande de fonctionnalité de boucle de crash dans #2504. Nous avons également le PR pour une connexion supplémentaire au #2315. Je vais fermer ce problème car il semble que tout le monde a débogué ses problèmes et maintenant nous avons des demandes de fonctionnalités et des améliorations pour aider les autres à l'avenir. Merci tout le monde!

Cette page vous a été utile?
0 / 5 - 0 notes