<p>gunicorn TEMPS D'ARRÊT DU TRAVAILLEUR CRITIQUE</p>

Créé le 21 janv. 2017  ·  18Commentaires  ·  Source: benoitc/gunicorn

J'exécute un gunicorn avec les paramètres suivants :
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 et je vois dans tous les travailleurs sauf 3 le [CRITICAL] WORKER TIMEOUT . Après un certain temps, le gunicorn ne peut plus générer de travailleurs ou du moins est très lent à les générer. Cela l'amène à ne pas rendre le serveur accessible et toute demande inaccessible.

J'ai réduit le nombre de travailleurs à 3 et donné à chaque travailleur 2 threads et maintenant je ne vois plus ce problème.

Je ne peux pas obtenir de trace de pile à partir des délais d'attente, mais il semble qu'après un certain nombre de travailleurs, il ne puisse pas les gérer?

( unconfirmed - Bugs -

Commentaire le plus utile

Pour toute personne ayant encore ce problème, veuillez vérifier la disponibilité des ressources pour l'application en plus d'augmenter le délai d'expiration et de modifier le type de classe de travailleurs

J'avais ce problème lorsque j'essayais de déployer mon application à l'aide de Docker Swarm et j'ai réalisé que je limitais trop la ressource pour l'application. L'augmentation des ressources résout le problème pour moi

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

Je pense que ce n'est pas un bug, juste comment nous configurons nos applications

Tous les 18 commentaires

lorsqu'un travailleur expire, cela signifie qu'il n'a pas informé l'arbitre à temps qu'il était en vie. Avez-vous une tâche exécutée pendant une requête qui pourrait prendre plus de temps que le délai d'attente ?

@jseaidou bosse.

Désolé pour la réponse tardive @benoitc. Le problème que je vois est en fait les threads non actifs qui le font. Mes threads actifs n'expirent pas, mes threads non actifs sous moins de charge donnent des erreurs de temporisation plus critiques que de simplement expirer gracieusement. Je suis passé de gevent à tornado et cela semble avoir résolu le problème de blocage, mais je vois toujours 3 travailleurs donner systématiquement le délai d'attente critique toutes les 30 secondes. S'il s'agit d'un délai d'attente normal, il ne devrait pas s'agir d'une erreur critique.

Je suis confronté exactement au même problème.
Gunicorne 19.7.1
événement 1.2.1
Python 3.5.3
Fonctionnant dans Docker, image basée sur " python:3.5 " officiel

@jseaidou c'est un délai d'attente normal dans le sens où l'arbitre y réagit. C'est essentiel car cela ne devrait normalement pas arriver.

Très probablement, l'un de vos travailleurs fait une opération de blocage empêchant le travailleur gunicorn d'informer l'arbitre. Si vous avez une longue opération, assurez-vous de déclencher le planificateur geven de temps en temps en dormant ou autre. ou tout ce qui rappelle aussi le programmateur de tornade.

Comment reproduire le problème ?

@saabeilin pareil ^^

Je constate la même chose : les travailleurs expirent même lorsqu'ils ne répondent à aucune demande. Tout ce que j'ai fait, c'est lancer mon conteneur sur 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

Cela ne se produit pas lors de l'exécution locale. :-/

On dirait que le passage aux travailleurs gevent a résolu le problème pour moi. \_(ツ)_/¯

Duplicata du #1194, je pense.

J'ai vu cela se produire à plusieurs reprises ces derniers temps, et pour moi, cela semble lié à la mise en veille de l'ordinateur portable. Lorsque j'ouvre le couvercle, un tas de ces messages s'affichent. Je ne suis pas sûr que cela aide, mais j'ai pensé que je le mentionnerais…

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:app

délai d'attente 30 secondes
OBTENIR la demande

Ubuntu 16.04
flacon 0,12.2
Python 3.6.3 (par défaut, le 4 octobre 2017, 02:55:45)
[GCC 5.4.0 20160609] sur Linux
gunicorn (version 19.7.1)

J'ai rencontré le problème.

Juste après avoir lancé l'application, cela fonctionne. Mais seulement s'il y a une demande, [CRITICAL] WORKER TIMEOUT sera déclenché. Par exemple,

[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

Quand j'ai basculé la classe ouvrière sur eventlet , c'est,
gunicorn --worker-class eventlet --log-level debug --bind 0.0.0.0:8080 app ,
c'est bon.

Remarque : Mon application s'exécute sur l'hôte physique, ni sur l'hôte virtuel ni sur l'hôte cloud.


Mettre à jour:

Donc je suppose que c'est la question de gevent ou de gevent worker.

Il existe des rapports sur cette question de gevent résolvant le problème et gevent causant le problème. Je ne peux pas identifier une cause racine ici. Certains des rapports peuvent être les mêmes que le 1194, mais d'autres peut-être pas.

Si quelqu'un peut partager un cas minimal à reproduire, cela aiderait.

Je ne suis pas sûr qu'il s'agisse du même problème, mais je peux le reproduire à 100 % du temps en utilisant Virtualbox avec la configuration suivante :

Hébergeur : Windows 10
Invité : Ubuntu 16.04
Gunicorne : 19.7.1

Je transfère TCP:8000 entre l'hôte et l'invité via la connexion NAT par défaut. En utilisant un travailleur sync , toutes les demandes sur l' hôte pour localhost:8000 provoquent l'apparition de ces erreurs dans le journal, mais si je fais les mêmes demandes sur l' invité , le journal est clair. Le passage à --worker-class eventlet supprime la trace.

J'apprécie que Virtualbox soit une dimension complètement différente, mais cela ressemble beaucoup à ce qui est décrit ci-dessus et est toujours reproductible (pour moi du moins).

Je vois cela se produire avec des téléchargements lents. Lors d'un téléchargement (vers un site Django) si le délai d'expiration du travailleur est atteint, le téléchargement meurt.

@lordmauve si vous utilisez le travailleur de synchronisation attendu. Les requêtes longues bloqueront le travailleur et finalement l'arbitre le tuera. Vous pouvez utiliser un type de nœud de calcul différent si vous vous attendez à ce que les requêtes longues aboutissent.

Pour tous ceux qui lisent ce fil, veuillez rouvrir avec un cas minimal à reproduire. Je ne vois aucune enquête propre à poursuivre ici. Pour le cas d'AWS/ECS, je laisse toujours le #1194 ouvert jusqu'à ce que je puisse tester les configurations que j'ai listées (https://github.com/benoitc/gunicorn/issues/1194#issuecomment-371250650).

Pour toute personne ayant encore ce problème, veuillez vérifier la disponibilité des ressources pour l'application en plus d'augmenter le délai d'expiration et de modifier le type de classe de travailleurs

J'avais ce problème lorsque j'essayais de déployer mon application à l'aide de Docker Swarm et j'ai réalisé que je limitais trop la ressource pour l'application. L'augmentation des ressources résout le problème pour moi

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

Je pense que ce n'est pas un bug, juste comment nous configurons nos applications

@jseaidou c'est un délai d'attente normal dans le sens où l'arbitre y réagit. C'est essentiel car cela ne devrait normalement pas arriver.

Très probablement, l'un de vos travailleurs fait une opération de blocage empêchant le travailleur gunicorn d'informer l'arbitre. Si vous avez une longue opération, assurez-vous de déclencher le planificateur geven de temps en temps en dormant ou autre. ou tout ce qui rappelle aussi le programmateur de tornade.

Comment reproduire le problème ?

@saabeilin pareil ^^

Merci, c'est logique.
Pour moi, cela se produit lors du service d'un fichier volumineux précédemment téléchargé à partir du stockage en nuage.
Sur demande, le fichier est récupéré sur le disque local à partir du stockage en nuage, puis il est déchiffré par flux vers le client. Le téléchargement depuis le stockage cloud fonctionne bien, même si cela prend 10 minutes ou plus.
Une fois que le travailleur commence à déchiffrer le fichier du disque vers le client, il meurt après quelques centaines de Mo, probablement parce qu'il expire pendant qu'il est occupé par cette opération de blocage.

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