Gunicorn: Les travailleurs de la synchronisation Gunicorn expirent sur docker + AWS

Créé le 29 janv. 2016  ·  78Commentaires  ·  Source: benoitc/gunicorn

En utilisant gunicorn 19.4.5 dans une image docker, qui s'exécute sur Ubuntu 14.04 LTS sur AWS, je vois des délais d'expiration constants lors de l'exécution avec > 1 travailleur de synchronisation et le délai d'expiration par défaut de 30 s. Cela peut être lié à #588 ou #942, bien qu'il s'agisse d'une version beaucoup plus récente de gunicorn, donc je ne peux pas le dire avec certitude.

Des preuves circonstancielles sur plusieurs passages semblent suggérer qu'un des travailleurs n'est pas affecté et que seuls les travailleurs N-1 restants échouent et redémarrent. Cependant, je n'ai pu obtenir que quelques points de données qui suggèrent cela, alors ne le prenez pas comme un signal fort.

Voici les choses que j'ai vérifiées :

  • Les problèmes se produisent-ils en dehors de docker ou lors de l'utilisation de la même image docker, mais pas sur AWS ?
    Non, je n'ai pu reproduire le problème qu'avec docker sur AWS.
  • L'application prend-elle plus de 30 s pour s'initialiser ?
    Non, l'application finit de s'initialiser en moins d'1 seconde.
  • L'application reçoit-elle une demande qui la fait se bloquer ?
    Le problème est apparu sans qu'aucune demande ne soit faite à l'application.
  • L'application a-t-elle un code d'initialisation cassé qui confond gunicorn ?
    Le problème est apparu lors de l'exécution de gunicorn dans la même configuration (avec > 1 travailleur de synchronisation), mais avec une application différente. Cette nouvelle application fonctionne sans problème sur gunicorn lors de l'utilisation de travailleurs gevent.
  • Le système de fichiers de docker ne parvient-il pas à mettre à jour le ctime ?
    Voir le journal ci-dessous - le ctime semble généralement avancer correctement. Le système de fichiers de Docker n'autorise pas stat -L sur les fichiers supprimés, mais empêcher gunicorn de dissocier le fichier entraîne également stat -L indiquant que ctime est mis à jour comme d'habitude.

J'ai ajouté du code à workertmp.py pour enregistrer le temps de lecture à chaque vérification, et voici un tel journal (entrelacé entre tous les travailleurs):

[2016-01-29 00:21:38 +0000] [3238] [INFO] Starting gunicorn 19.4.0
[2016-01-29 00:21:38 +0000] [3238] [INFO] Listening at: http://0.0.0.0:5000 (3238)
[2016-01-29 00:21:38 +0000] [3238] [INFO] Using worker: sync
[2016-01-29 00:21:38 +0000] [3243] [INFO] Booting worker with pid: 3243
[2016-01-29 00:21:38 +0000] [3244] [INFO] Booting worker with pid: 3244
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026899.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026899.03
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026900.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026899.03
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026900.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026899.03
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026900.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026899.03
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026900.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026899.03
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026904.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026899.03
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026904.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026905.0
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026904.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026905.0
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026904.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026905.0
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026904.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026905.0
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026904.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026909.74
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026910.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026909.74
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026910.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026909.74
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026910.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026909.74
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026910.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026909.74
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026914.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026914.74
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026914.74
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026914.74
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026914.74
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026914.74
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026914.74
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026914.74
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026914.74
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026914.74
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026914.74
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026914.74
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026914.74
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026914.74
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026914.74
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026914.74
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026914.74
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026914.74
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026914.74
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026914.74
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026933.73
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026934.74
FOOBAR: modify /tmp/wgun[2016-01-29 00:22:25 +0000] [3238] [CRITICAL] WORKER TIMEOUT (pid:3243)
[2016-01-29 00:22:25 +0000] [3243] [INFO] Worker exiting (pid: 3243)
[2016-01-29 00:22:25 +0000] [3330] [INFO] Booting worker with pid: 3330
icorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026935.0
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026935.0
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026935.0
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026935.0
FOOBAR: modify /tmp/wgunic54026934.74
FOOBAR: modify /tmp/wgun[2016-01-29 00:22:25 +0000] [3238] [CRITICAL] WORKER TIMEOUT (pid:3243)
[2016-01-29 00:22:25 +0000] [3243] [INFO] Worker exiting (pid: 3243)
[2016-01-29 00:22:25 +0000] [3330] [INFO] Booting worker with pid: 3330
icorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time:fy] [3238] [CRITICAL] WORKER TIMEOUT (pid:3243)
[2016-01-29 00p/2:25 +0000] [3243] [INFO] Worker exiting (pid: 3243)
[2016-0ic29 00:22:25 +0000] [3330] [INFO] Booting worker with pid: 33myicorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorntiyjLwI time: 1454026935.0
FOOBAR: modify /tmp/wgunicorn-RhAFmt45ime: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026945.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026945.8
FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026945.82
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026945.8
FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026946.01
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026945.8
FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026946.01
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026945.8
FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026946.01
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026945.8corn-myjLwI time:fy] [3238] [CRITICAL] WORKER TIMEOUT (pid:32BA)
[2016-01-29 00p/2:25 +0000] [3243] [INFO] Worker exiting (pdify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026945.8
FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026945.8
FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026945.8
FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026945.8
FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026945.8
FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026945.8
FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026945.8
FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026945.8
FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026945.8
FOOBAR: modify /tAR: modify /tmp/wgunicorn-myjLwI time: 1454026945.8
FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026945.8
FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026945.8
FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026945.8
FOOBAR: modify /tAR: modify /tmp/wgunicorn-myjLwI time: 1454026945.8
FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026945.8
FOOBAR: modify /tmp/wgunicorn-Mw64T1 timeodify /tmp/wgunicorn-myjLwI time: 1454026964.74
FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026965.0
FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026965.0
FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026965.0
FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026965.0
FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026969.74
FOO[2016-01-29 00:22:59 +0000] [3238] [CRITICAL] WORKER TIMEOUT (pid:3330)
[2016-01-29 00:22:59 +0000] [3330] [INFO] Worker exiting (pid: 3330)
icorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026935.0
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026935.0
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026935.0
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026935.0
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026939.74
FOOBAR: modify /tmp/wgunicorn-LwI time: 1454026965.0
FOOBAR: modify /tmp/wgunicorn-Mw64T1 tI time: 1454026940.0
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026940.0
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026940.0
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026940.0
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026944.74
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026945.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026945.8
[2016-01-29 00:22:59 +0000] [3396] [INFO] Booting worker with pid: 3396
BAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026970.0
FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026970.0
FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
FOOBAR: modify /tmp/wgunicorn-myjL26949.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026970.0
FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
FOOBAR: modify /tmp/wgunicorn-myjL26949.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026970.0
FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
FOOBAR: modify /tmp/wgunicorn-myjL26949.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026970.0
FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
FOOBAR: modify /tmp/wgunicorn-myjL26949.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026970.0
FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
FOOBAR: modify /tmp/wgunicorn-myjL26949.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026970.0
FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
FOOBAR: modify /tmp/wgunicorn-myjL26949.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026970.0
FOOBAR: modify /tmp/w79.95
FOOBAR: modify /tmp/wgunicorn-k3uZLy time: 1454026979.97
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026979.95
FOOBAR: modify /tmp/wgunicorn-k3uZLy time: 1454026980.16
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026979.95
FOOBAR: modify /tmp/wgunicorn-k3uZLy time: 1454026980.16
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026979.95
FOOBAR: modify /tmp/wgunicorn-k3uZLy time: 1454026980.16
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026979.95
FOOBAR: modify /tmp/wgunicorn-k3uZLy time: 1454026980.16
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026979.95
FOOBAR: modify /tmp/wgunicorn-k3uZLy time: 1454026980.16
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026979.95
FOOBAR: modify /tmp/wgunicorn-k3uZLy time: 1454026980.16
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026979.95
FOOBAR: modify /tmp/wgunicorn-k3uZLy time: 1454026980.16
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026979.95
FOOBAR: modify /tmp/wgunicorn-k3uZLy time: 1454026980.16
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026979.95
FOOBAR: modify /tmp/wgunicorn-k3uZLy time: 1454026980.16
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026979.95
80.16
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026979.95
FOOBAR: modify /tmp/wgunicorn-k3uZLy time: 1454026980.16
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026979.95
FOOBAR: modify /tmp/wgunicorn-k3uZLy time: 1454026980.16
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026979.95
FOOBAR: modify /tmp/wgunicorn-k3uZLy time: 1454026980.16
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026979.95
FOOBAR: modify /tmp/wgunicorn-k3uZLy time: 1454026980.16
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026979.95
FOOBAR: modify /tmp/wgunicorn-k3uZLy time: 1454026980.16
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026979.95
FOOBAR: modify /tmp/wgunicorn-k3uZLy time: 1454026980.16
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026979.95
FOOBAR: modify /tmp/wgunicorn-k3uZLy time: 1454026980.16
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026979.95
FOOBAR: modify /tmp/wgunicorn-k3uZLy time: 1454026980.16
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026979.95
FOOBAR: modify /tmp/wgunicorn-k3uZLy time: 1454029.95
FOOBAR: modify /tmp/wgunicorn-k3uZLy time: 1454026980.16
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026979.95
FOOBAR: modify /tmp/wgunicorn-k3uZLy time: 1454026980.16
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026979.95
FOOBAR: modify /tmp/wgunicorn-k3uZLy time: 1454029.95
FOOBAR: modify /tmp/wgunicorn-k3uZLy time: 1454026980.16
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026979.95
FOOBAR: modify /tmp/wgunicorn-k3uZLy time: 1454026980.16
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026979.95
FOOBAR: modify /tmp/wgunicorn-k3uZLy time: 1454029.95
FOOBAR: modify /tmp/wgunicorn-k3uZLy time: 1454026980.16
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026979.95
FOOBAR: modify /tmp/wgunicorn-k3uZLy time: 1454026980.16
 WORKER TIMEOUT (pid:3396)
 [2016-01-29 00:23:31 +0000] [3396] [INFO] Worker exiting (pid: 3396)
 BAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026970.0
 FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026970.0
 FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026970.0
 FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026970.0
 FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026974.74
 FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026975.0
 FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026975.0
 FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026975.0
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026975.0
 FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026975.0
 FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026975.0
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026975.0
 FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026975.0
 FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026975.0
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026975.0
 FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026975.0
 FOOBAR: modify /tmp/wgunicorn-Mw6nicorn-k3uZLy time: 1454026980.16
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454027005.0
 FOOBAR: modify /tmp/wgunicorn-k3uZLy time: 1454026980.16
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454027010.0
 FOOBAR: modify /tmp/wgunicorn-k3uZLy time: 1454026980.16
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454027010.0
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454027011.06
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454027011.06
 FOOBAR: modify /tmp/wgunicorn-ZmVaVS time: 1454027011.08
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454027011.06
 FOOBAR: modify /tmp/wgunicorn-ZmVaVS time: 1454027011.28
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454027011.06
 FOOBAR: modify /tmp/wgunicorn-ZmVaVS time: 1454027011.28
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454027011.06
 FOOBAR: modify /tmp/wgunicorn-ZmVaVS time: 1454027011.28
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454027011.06
 FOOBAR: modify /tmp/wgunicorn-ZmVaVS time: 1454027014.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454027011.06
 FOOBAR: modify /tmp/wgunicorn-ZmVaVS time: 1454027014.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454027011.06
 FOOBAR: modify /tmp/wgunicorn-ZmVaVS time: 1454027014.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454027011.06
 FOOBAR: modify /tmp/wgunicorn-ZmVaVS time: 1454027014.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454027011.06
 FOOBAR: modify /tmp/wgunicorn-ZmVaVS time: 1454027014.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454027011.06
 FOOBAR: modify /tmp/wgunicorn-ZmVaVS time: 1454027014.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454027011.06
 FOOBAR: modify /tmp/wgunicorn-ZmVaVS time: 1454027014.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454027011.06
 FOOBAR: modify /tmprn-myjLwI time: 1454027011.06
 FOOBAR: modify /tmp/wgunicorn-Znicorn-myjLwI time: 1454027011.06
 FOOBAR: modify /tmp/wgunicorn-ZmVaVS time: 1454027014.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454027011.06
 FOOBAR: modify /tmp/wgunicorn-ZmVaVS time: 1454027014.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454027011.06
 FOOBAR: modify /tmp/wgunicorn-ZmVaVS time: 1454027014.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454027011.06
 FOOBAR: modify /tmp/wgunicorn-ZmVaVS time: 1454027014.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454027011.06
 FOOBAR: modify /tmp/wgunicorn-ZmVaVS time: 1454027014.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454027011.06
 FOOBAR: modify /tmp/wgunicorn-ZmVaVS time: 1454027014.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454027028.98
 FOOBAR: modify /tmp/wgunicorn-ZmVaVS time: 1454027014.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454027030.0
 FOOBAR: modify /tmp/wgunicorn-ZmVaVS time: 1454027014.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454027030.0
 FOOBAR: modify /tmp/wgunicorn-ZmVaVS time: 1454027014.74
 FOOBAR: modify /tmp/wguicorn-ZmVaVS time: 1454027014.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454027030.0
 FOOBAR: modify /tmp/wgunicorn-ZmVaVS time: 1454027014.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454027030.0
 FOOBAR: modify /tmp/wgunicorn-ZmVaVS time: 1454027014.74
 FOOBAR: modify /tmp/wguicorn-ZmVaVS time: 1454027014.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454027030.0
 FOOBAR: modify /tmp/wgunicorn-ZmVaVS time: 1454027014.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454027030.0
 FOOBAR: modify /tmp/wgunicorn-ZmVaVS time: 1454027014.74
 FOOBAR: modify /tmp/wguicorn-ZmVaVS time: 1454027014.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454027030.0
 FOOBAR: modify /tmp/wgunicorn-ZmVaVS time: 1454027014.74
 FOOBAR: modify /tmp/wgunicorn--ZmVaVS time: 1454027014.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454027035.0
 FOOBAR: modify /tmp/wgunicorn-ZmVaVS time: 1454027014.74
 FOOBAR: modify /t[2016-01-29 00:24:05 +0000] [3238] [CRITICAL] WORKER TIMEOUT (pid:3453)
 [2016-01-29 00:24:05 +0000] [3453] [INFO] Worker exiting (pid: 3453)
FeaturIPC PlatforDocker - Bugs -

Commentaire le plus utile

Essayez d'utiliser les travailleurs gevent place, cela a résolu le problème pour moi.

Tous les 78 commentaires

hrmmm à partir du journal ci-dessus, je peux voir que l'heure ne change jamais. je vérifierai

Merci, j'apprécie !

Je pourrais être affecté par ce bug.

J'exécute gunicorn dans une image Docker sur AWS (Elastic Beanstalk + EC2 Container Service).
Il y a des délais d'expiration de travail constants qui commencent à se produire presque immédiatement après l'initialisation, et uniquement lors de l'exécution de l'image Docker sur AWS.
La même requête HTTP prend parfois quelques ms, parfois 20-30 secondes. Peu importe qu'il s'agisse d'une page inexistante, d'une simple page de chaîne "Hello world" non authentifiée ou d'une page qui récupère les enregistrements d'une base de données.

Détails supplémentaires :

  • Versions Gunicorne : 19.5.0 et 19.6.0.
  • Image Docker de base : python:3.4 ( OS : Debian Jessie)
  • Version Docker : 1.9.1 (géré par Amazon ECS), OS : Amazon Linux AMI 2016.03 (géré par Amazon EB).
  • Framework d'application Web : Django versions 1.9.6 et 1.9.7.

Environnements _non_ affectés :

  • Machine locale , à la fois _à l'intérieur_ et _à l'extérieur_ d'un conteneur Docker. OS : Ubuntu 16.04 LTS, Docker : 1.11.2.
  • Heroku ( OS : Ubuntu 14.04 LTS)

Journaux de conteneur Amazon :

[2016-06-15 16:46:15 +0000] [1] [DEBUG] Current configuration:
  cert_reqs: 0
  post_request: <function PostRequest.post_request at 0x7fb13e187c80>
  worker_connections: 1000
  tmp_upload_dir: None
  enable_stdio_inheritance: False
  timeout: 30
  pre_fork: <function Prefork.pre_fork at 0x7fb13e1871e0>
  worker_int: <function WorkerInt.worker_int at 0x7fb13e1876a8>
  backlog: 2048
  max_requests: 0
  max_requests_jitter: 0
  access_log_format: %(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s"
  logconfig: None
  syslog_addr: udp://localhost:514
  preload_app: False
  pidfile: None
  umask: 0
  secure_scheme_headers: {'X-FORWARDED-PROTOCOL': 'ssl', 'X-FORWARDED-PROTO': 'https', 'X-FORWARDED-SSL': 'on'}
  paste: None
  proxy_protocol: False
  worker_class: sync
  on_starting: <function OnStarting.on_starting at 0x7fb13e414c80>
  worker_abort: <function WorkerAbort.worker_abort at 0x7fb13e187840>
  worker_exit: <function WorkerExit.worker_exit at 0x7fb13e187e18>
  config: config/gunicorn.py
  nworkers_changed: <function NumWorkersChanged.nworkers_changed at 0x7fb13e18a048>
  daemon: False
  accesslog: None
  errorlog: -
  loglevel: debug
  syslog_prefix: None
  ssl_version: 3
  suppress_ragged_eofs: True
  limit_request_field_size: 8190
  reload: False
  logger_class: gunicorn.glogging.Logger
  statsd_host: None
  keyfile: None
  raw_env: []
  threads: 1
  django_settings: None
  proc_name: None
  proxy_allow_ips: ['127.0.0.1']
  limit_request_fields: 100
  ciphers: TLSv1
  check_config: False
  do_handshake_on_connect: False
  post_worker_init: <function PostWorkerInit.post_worker_init at 0x7fb13e187510>
  graceful_timeout: 30
  worker_tmp_dir: None
  certfile: None
  sendfile: None
  keepalive: 2
  chdir: /app/testapp
  when_ready: <function WhenReady.when_ready at 0x7fb13e187048>
  ca_certs: None
  on_exit: <function OnExit.on_exit at 0x7fb13e18a1e0>
  spew: False
  bind: [':8000']
  post_fork: <function Postfork.post_fork at 0x7fb13e187378>
  limit_request_line: 4094
  syslog_facility: user
  workers: 3
  syslog: False
  pre_request: <function PreRequest.pre_request at 0x7fb13e187b70>
  user: 0
  group: 0
  forwarded_allow_ips: ['127.0.0.1']
  pythonpath: None
  on_reload: <function OnReload.on_reload at 0x7fb13e414e18>
  pre_exec: <function PreExec.pre_exec at 0x7fb13e1879d8>
  default_proc_name: config.wsgi
  statsd_prefix: 
[2016-06-15 16:46:15 +0000] [1] [INFO] Starting gunicorn 19.5.0
[2016-06-15 16:46:15 +0000] [1] [DEBUG] Arbiter booted
[2016-06-15 16:46:15 +0000] [1] [INFO] Listening at: http://0.0.0.0:8000 (1)
[2016-06-15 16:46:15 +0000] [1] [INFO] Using worker: sync
[2016-06-15 16:46:15 +0000] [8] [INFO] Booting worker with pid: 8
[2016-06-15 16:46:15 +0000] [9] [INFO] Booting worker with pid: 9
[2016-06-15 16:46:15 +0000] [10] [INFO] Booting worker with pid: 10
[2016-06-15 16:46:15 +0000] [1] [DEBUG] 3 workers
[2016-06-15 16:46:52 +0000] [1] [CRITICAL] WORKER TIMEOUT (pid:9)
[2016-06-15 16:46:52 +0000] [9] [INFO] Worker exiting (pid: 9)
[2016-06-15 16:46:52 +0000] [1] [CRITICAL] WORKER TIMEOUT (pid:10)
[2016-06-15 16:46:52 +0000] [10] [INFO] Worker exiting (pid: 10)
[2016-06-15 16:46:53 +0000] [20] [INFO] Booting worker with pid: 20
[2016-06-15 16:46:53 +0000] [1] [DEBUG] 2 workers
[2016-06-15 16:46:53 +0000] [21] [INFO] Booting worker with pid: 21
[2016-06-15 16:46:53 +0000] [1] [DEBUG] 3 workers
[2016-06-15 16:47:23 +0000] [1] [CRITICAL] WORKER TIMEOUT (pid:8)
(...)

`

Merci.

Je vois ça aussi. Mon soupçon est l'Elastic Load Balancer. Nous utilisions paste dans une entreprise précédente et cela causait des problèmes avec l'ELB. Je pense qu'il réutilise les connexions d'une manière ou d'une autre et que cela provoquait des problèmes dans paste .

Je suis maintenant dans un nouveau travail où nous utilisons gunicorn et tout allait bien jusqu'à ce que nous commencions à mettre le serveur derrière un ELB, l'application Web est maintenant souvent très insensible et semble se bloquer.

Essayez d'utiliser les travailleurs gevent place, cela a résolu le problème pour moi.

Est-ce donc un problème avec l'ELB qui maintient les connexions en vie et attache le travailleur de synchronisation? Cela me semblerait très étrange puisque nous signalons délibérément que la connexion doit être fermée avec le travailleur de synchronisation : https://github.com/benoitc/gunicorn/blob/master/gunicorn/workers/sync.py#L168

Nous pourrions cependant fermer la connexion délibérément. Si quelqu'un veut tester le déplacement de l'appel client.close() pour qu'il soit inconditionnel, cela pourrait être un test intéressant : https://github.com/benoitc/gunicorn/blob/master/gunicorn/workers/sync.py#L199

Vous pouvez également vous assurer que le délai d'inactivité sur l'ELB est inférieur au délai d'expiration du travailleur, afin de vérifier rapidement que c'est même la cause du problème : http://docs.aws.amazon.com/elasticloadbalancing/latest/ classic/config-idle-timeout.html

@tilgovi la chose elb est ma meilleure supposition actuelle, car a) cela ne se produit que si le gunicorn est derrière un ELB et b) le problème est résolu en utilisant le travailleur gevent . Mais encore une fois, qui sait...

cela se produit uniquement derrière ELB et si le protocole HTTP ou HTTPS est défini sur ELB.
Si vous changez de protocole en TCP ou SSL, le problème disparaît.
Est-ce que quelqu'un sait comment le résoudre en utilisant toujours les travailleurs de synchronisation ? J'ai utilisé le correctif que j'ai décrit (TCP au lieu de HTTP) jusqu'à présent, lorsque je vais surveiller les journaux d'accès et voir l'en-tête X-Forwarded-For, qui n'est activé que pour HTTP/HTTPS sur ELB :)

Étrange, juste pour s'assurer que nous sommes sur la même longueur d'onde, cela signifie qu'il y a une sorte d'optimisation lors de l'utilisation de l'option HTTP/HTTPS dans l'ELB ? Et cette optimisation cause des problèmes avec les travailleurs de synchronisation ?

@ecs Je pense que dans le cas d'un équilibreur de charge HTTP/HTTPS, réutilisez la même connexion TCP, qui est maintenue par ELB en vie pendant longtemps - une sorte de ça. Mais cela n'explique pas pourquoi gevent worker fonctionne bien... (bien que je n'aie pas encore testé gevent, il suffit de lire ces commentaires)

D'ailleurs, il y a certainement beaucoup de facteurs (version gunicorne, classe de travailleurs, docker interne ou non, protocole ELB) qui peuvent influencer, donc ce pourrait être génial si quelqu'un teste et confirme que le protocole TCP sur ELB fonctionne contrairement à HTTP. Je teste sur docker hébergé sur Ubuntu 14.04 et gunicorn version 19.3.0

J'ai le même problème:
[2016-10-03 12:13:17 +0000] [6] [CRITIQUE] TEMPS D'INTERVENTION DU TRAVAILLEUR (pid:16)
[2016-10-03 12:13:17 +0000] [16] [INFO] Sortie du travailleur (pid: 16)
[2016-10-03 12:13:17 +0000] [6] [CRITIQUE] TEMPS D'INTERVENTION DU TRAVAILLEUR (pid:20)
[2016-10-03 12:13:17 +0000] [20] [INFO] Sortie du travailleur (pid: 20)
[2016-10-03 12:13:17 +0000] [33] [INFO] Amorçage du travailleur avec pid : 33

Ma configuration.

J'utilise kube-aws pour configurer un cluster kubernetes avec core-os sur AWS : https://github.com/coreos/coreos-kubernetes/tree/master/multi-node/aws

J'ai une application python utilisant gunicorn et les travailleurs de synchronisation. Le service pour eux utilise un équilibreur de charge HTTPS avec le certificat de mes sites. Tous les travailleurs sont considérés comme ayant expiré après le délai d'expiration par défaut de 30 s, semble-t-il. Ils sont finalement tous redémarrés. Kubernetes redémarre finalement le conteneur lorsqu'il se ferme. Ces redémarrages se produisent en continu. Quelqu'un ci-dessus a mentionné que gevent résout le problème, je peux essayer cela, mais j'aimerais vraiment comprendre pourquoi cela se produit.

Nous rencontrons également ce problème actuellement, j'essaierai de publier plus de détails lorsque j'en aurai l'occasion. Il est lié au travailleur de synchronisation car le passage à gevent résout effectivement le problème. C'est sur AWS avec ECS et ELB.

J'ai également eu le même problème étrange avec l'une de nos applications. Changer les écouteurs de HTTP en tcp résout en effet le problème.

quelqu'un peut-il me fournir un moyen étape par étape pour reproduire le problème? (étape de configuration et autres) Ou du moins, indiquez-moi un moyen simple de configurer cet environnement :) J'y jetterai un coup d'œil cette semaine.

S'appuyer sur HTTP pour un tel équilibreur nécessite généralement de gérer la persistance (à l'exception de tcp), donc tout ce qui utilise un travailleur de synchronisation peut être un problème jusqu'à ce que le travailleur de synchronisation soit mis à jour pour sa prise en charge.

Quoi qu'il en soit, tiens-moi au courant.

Configurez simplement une application Flask de base et exécutez-la avec gunicorn avec des travailleurs de synchronisation dans docker sur AWS, avec l'équilibrage de charge HTTP et la configuration ci-dessus :

En utilisant gunicorn 19.4.5 dans une image docker, qui s'exécute sur Ubuntu 14.04 LTS sur AWS, je vois des délais d'expiration constants lors de l'exécution avec > 1 travailleur de synchronisation et le délai d'expiration par défaut de 30 s.

Vous n'avez pas à faire de requêtes à l'application, surveillez simplement les journaux et vous verrez que les travailleurs expirent.

  • Je peux confirmer ce comportement ainsi que l'approche de base pour le reproduire.

    • Le comportement n'est pas limité à Docker mais plutôt au travailleur de synchronisation / au paramètre keepalive, vous pouvez donc envisager de changer le titre...

  • J'ai modifié le paramètre keepalive pour suivre ce qui est décrit ici : https://serverfault.com/questions/782022/keepalive-setting-for-gunicorn-behind-elb-without-nginx/ (la partie la plus intéressante est la citation de la documentation AWS ELB) et a constaté que le serveur ne présentait plus ce comportement.
  • De plus, j'ai également changé pour la classe d'ouvriers gthread et j'ai trouvé le résultat très acceptable jusqu'à présent.

J'utilise actuellement des travailleurs gevent avec un délai d'attente de 65 s (le délai d'attente d'AWS ELB est de 60 s, AFAIK). J'ai encore parfois 504 erreurs même lorsqu'un seul client fait des demandes, avec 1 demande en vol à la fois, mais je n'ai pas encore réussi à identifier une raison.

@ obi1kenobi Avez-vous essayé d'augmenter la durée de vie au-delà de l'option de délai d'attente ELB ?

@lenucksi le keepalive est déjà plus élevé que le délai d'attente ELB de 5 s - j'espère que les horloges des serveurs ne conduisent pas autant :)

J'ai également rencontré ce problème en exécutant gunicorn 19.6 dans un conteneur Docker sur une instance EC2 derrière un ELB (en utilisant le protocole HTTP par défaut pour le proxy inverse vers l'instance EC2).

Comme suggéré précédemment, la définition de la classe de travailleurs sur gevent a résolu ce problème pour moi (là où j'utilisais auparavant la classe de travailleurs sync par défaut).

Je vais essayer de documenter un exemple minimal pour reproduire le problème.

Pour corroborer ce que d'autres ont dit, l'ELB semble ouvrir une connexion à l'instance EC2 et la maintenir ouverte de manière à empêcher gunicorn de traiter des demandes supplémentaires.

Lorsque cette connexion maintenue ouverte se termine en raison du délai d'expiration de la demande de l'ELB par gunicorn, toutes les demandes en attente mises en file d'attente derrière elle échouent également (y compris la vérification de l'état de l'ELB, entraînant la suppression de l'instance de l'ELB, ce qui rend le débogage plus difficile ; ) ).

Ce symptôme suggère qu'il s'agit d'un doublon de ce qui a été observé dans ce numéro précédent qui n'est pas lié à Docker : https://github.com/benoitc/gunicorn/issues/588

@jelis Savez-vous si cela est lié à certaines configurations de kubernetes ? Votre problème a-t-il été résolu ?

Je suis également sur un ELB avec terminaison SSL. Je vois ça dans mes logs :

[017-03-01 07:36:32 +0000] [1249] [DEBUG] GET /healthcheck
[01/Mar/2017:07:36:32 +0000] "GET /healthcheck HTTP/1.1" 200 22 "-" "ELB-HealthChecker/1.0"
[017-03-01 07:36:37 +0000] [12] [CRITICAL] WORKER TIMEOUT (pid:1203)
[017-03-01 07:36:37 +0000] [12] [CRITICAL] WORKER TIMEOUT (pid:1225)
[017-03-01 07:36:37 +0000] [12] [CRITICAL] WORKER TIMEOUT (pid:1234)
[017-03-01 07:36:37 +0000] [12] [CRITICAL] WORKER TIMEOUT (pid:1243)
[017-03-01 07:36:37 +0000] [1203] [INFO] Worker exiting (pid: 1203)
[017-03-01 07:36:37 +0000] [1225] [INFO] Worker exiting (pid: 1225)
[017-03-01 07:36:37 +0000] [1243] [INFO] Worker exiting (pid: 1243)
[017-03-01 07:36:37 +0000] [1234] [INFO] Worker exiting (pid: 1234)
[017-03-01 07:36:37 +0000] [1256] [INFO] Booting worker with pid: 1256
[017-03-01 07:36:37 +0000] [12] [DEBUG] 14 workers
[017-03-01 07:36:37 +0000] [1257] [INFO] Booting worker with pid: 1257
[017-03-01 07:36:37 +0000] [1262] [INFO] Booting worker with pid: 1262
[017-03-01 07:36:37 +0000] [1265] [INFO] Booting worker with pid: 1265
[017-03-01 07:36:37 +0000] [12] [DEBUG] 16 workers
[017-03-01 07:36:40 +0000] [1262] [DEBUG] GET /healthcheck

Mise à jour - Je viens de passer de gunicorn à gevent (http://flask.pocoo.org/docs/0.12/deploying/wsgi-standalone/#gevent) et le problème est résolu. Ceci est en référence à mon commentaire ci-dessus https://github.com/benoitc/gunicorn/issues/1194#issuecomment -283269046

Je martèle ce problème depuis quelques jours. Les notes de chacun ici sont fantastiques et nous donnent un certain nombre de pistes pour rechercher des correctifs/solutions de contournement/atténuations. (le journal de mon travail est dans le bug que nous suivons ici )

Je viens d'essayer d'utiliser gevent avec une augmentation du nombre de travailleurs et cela ne nous a pas du tout aidés - en fait, cela a étonnamment fait paraître pire - les cinq travailleurs de gevent sont morts en même temps, ce qui est un nouveau comportement de ce que j'ai lu plus haut :

[2017-03-30 23:38:37 +0000] [5] [INFO] Starting gunicorn 19.7.1
[2017-03-30 23:38:37 +0000] [5] [INFO] Listening at: http://0.0.0.0:8000 (5)
[2017-03-30 23:38:37 +0000] [5] [INFO] Using worker: eventlet
[2017-03-30 23:38:38 +0000] [8] [INFO] Booting worker with pid: 8
[2017-03-30 23:38:40 +0000] [9] [INFO] Booting worker with pid: 9
[2017-03-30 23:38:41 +0000] [11] [INFO] Booting worker with pid: 11
[2017-03-30 23:38:42 +0000] [12] [INFO] Booting worker with pid: 12
[2017-03-30 23:38:42 +0000] [10] [INFO] Booting worker with pid: 10
[2017-03-30 23:40:08 +0000] [5] [CRITICAL] WORKER TIMEOUT (pid:8)
[2017-03-30 23:40:12 +0000] [5] [CRITICAL] WORKER TIMEOUT (pid:9)
[2017-03-30 23:40:12 +0000] [5] [CRITICAL] WORKER TIMEOUT (pid:10)
[2017-03-30 23:40:12 +0000] [5] [CRITICAL] WORKER TIMEOUT (pid:11)
[2017-03-30 23:40:12 +0000] [5] [CRITICAL] WORKER TIMEOUT (pid:12)
[2017-03-30 23:40:13 +0000] [8] [INFO] Worker exiting (pid: 8)
[2017-03-30 23:40:13 +0000] [10] [INFO] Worker exiting (pid: 10)
[2017-03-30 23:40:16 +0000] [16] [INFO] Booting worker with pid: 16
[2017-03-30 23:40:16 +0000] [17] [INFO] Booting worker with pid: 17
[2017-03-30 23:40:18 +0000] [18] [INFO] Booting worker with pid: 18
[2017-03-30 23:40:20 +0000] [19] [INFO] Booting worker with pid: 19
[2017-03-30 23:40:23 +0000] [20] [INFO] Booting worker with pid: 20

C'est probablement une erreur de ma part, et ce n'était pas le même comportement que l'un de mes homologues du projet (avec une base de code similaire mais pas identique dans un déploiement AWS/CloudFormation/ALB/ECS presque identique). Cependant, j'ai pensé que je le signalerais au cas où cela inspirerait de nouvelles informations sur les interactions entre ALB, ECS, Docker et gunicorn.

J'ai une configuration similaire (convox exécutant ELB->ECS Docker Container->Gunicorn->Django) et je peux confirmer que les modifications de configuration suivantes semblent avoir aidé :

keepalive = 75 # needs to be longer than the ELB idle timeout
timeout = 90
worker_class = 'gevent'

J'ai réglé mon délai d'inactivité ELB à 60 secondes.

Avant de modifier ces paramètres, j'utilisais les valeurs par défaut pour keepalive, timeout et sync worker.

Fait intéressant, ce problème a commencé à apparaître à 4 heures du matin UTC le 10 avril. L'application fonctionnait correctement sans aucun changement depuis le jeudi précédent.

juste empiler, pas de docker, mais l'instance nue d'aws avait le même problème derrière un ELB. fonctionne NP sur osx, mais ubuntu16 avec un même problème ELB est apparu. gevent classe ouvrière

@erikcw semble avoir trouvé cette solution pour fonctionner. J'aimerais clore ce sujet. Si quelqu'un peut reproduire cela après avoir augmenté le délai d'expiration du travailleur Gunicorn et le délai d'expiration de keepalive, veuillez le dire.

Vous pouvez également réduire le délai d'inactivité pour ELB.

Un client dans la nature (ou un client malveillant) ne pourrait-il pas agir comme l'ELB et provoquer le même problème ?

@ six8 oui. ELB ne vous protège pas non plus de cela. La documentation en parle : http://docs.gunicorn.org/en/latest/design.html#choosing -a-worker-type

Certaines personnes ne se soucient pas de cette menace et souhaitent simplement déployer Gunicorn, à la périphérie ou derrière un ELB. Le problème abordé ici concerne les délais d'attente des travailleurs causés par l'ELB lui-même. Je voudrais fournir une configuration recommandée qui permet à gunicorn de fonctionner derrière ELB avec des travailleurs de synchronisation et sans proxy inverse supplémentaire.

J'ai essayé @erikcw la solution « et en changeant l'invocation de gunicorn à:

CMD [ "gunicorn", "-k", "gevent", "--timeout", "10", "--keep-alive", "75", "--paste", "/etc/jzoo/app.ini" ]

Malheureusement, cela n'aide pas :

[2017-07-04 08:36:23 +0000] [1] [CRITICAL] WORKER TIMEOUT (pid:24)
[2017-07-04 08:38:11 +0000] [1] [CRITICAL] WORKER TIMEOUT (pid:28)
[2017-07-04 08:39:39 +0000] [1] [CRITICAL] WORKER TIMEOUT (pid:29)
[2017-07-04 08:44:14 +0000] [1] [CRITICAL] WORKER TIMEOUT (pid:25)
[2017-07-04 08:44:55 +0000] [1] [CRITICAL] WORKER TIMEOUT (pid:31)

J'ai une application qui s'exécute sur ECS derrière un ALB avec les travailleurs de synchronisation Gunicorn. Je n'ai pas encore vu de problème.

Quelqu'un peut-il fournir un déploiement reproductible ?

empiler aussi. voir ce problème en utilisant Kubernetes sur AWS avec ELB. Actuellement, 8 travailleurs sont en cours d'exécution. Par https://serverfault.com/questions/782022/keepalive-setting-for-gunicorn-behind-elb-without-nginx/ , nous allons augmenter keepalive , et par ce fil va essayer d'utiliser à la place gevent workers. Mais pour le moment, ce qui échoue, ce sont certains tests de performances pour les appels d'API qui ne devraient pas bloquer / provoquer des délais d'attente par eux-mêmes. aimerait savoir ce qui se passe ici avec les travailleurs de sync . même si cela fonctionne selon certaines des bonnes directives de ce fil, nous aimerions un peu plus de confiance quant à ce qui se passe avant le déploiement en production.

La définition de --worker-class sur --worker-class gevent fonctionné pour moi. Merci pour les commentaires et l'aide !

@wichert c'est très étrange. Avec le travailleur gevent, les travailleurs doivent informer l'arbitre de leur vivacité sur un greenlet séparé de toute connexion. Votre paramètre keep-alive ne devrait pas du tout affecter cela. Quelque chose ne va pas avec votre application, tel que gevent ne fonctionne pas comme prévu, ou quelque chose au sujet de la configuration est problématique qui pourrait être commun à ces autres scénarios.

S'il vous plaît, tout le monde sur ce fil, fournissez une application qui reproduit ce problème. Je n'ai pas réussi à le reproduire. Sans étapes à reproduire, je suis tenté de fermer. Il y a un mélange de recommandations et peut-être de problèmes très différents enfouis dans ces commentaires. Il est difficile de savoir quoi faire avec ce problème.

@tilgovi J'ai rencontré ce problème lorsque je ne spécifiais pas la classe de travailleurs à gevent (par exemple, en utilisant le travailleur de synchronisation par défaut). Ma configuration est virtualenv utilisant pypy3 (PyPy 5.8.0-beta0), falcon 1.2, etc. (comprendre que Falcon n'est pas officiellement pris en charge avec pypy3). J'ai utilisé le cookiecutter de https://github.com/7ideas/cookiecutter-falcon et mis à niveau vers tous les derniers packages et en essayant de charger le sample_resource dans le navigateur et en le frappant plusieurs fois avec httpie verrait par intermittence l'erreur de plantage du travailleur ( par exemple, la demande serait retardée et je verrais l'erreur ; si je n'annulais pas la demande, elle finirait par répondre). Cela ne s'est produit qu'avec la classe de travail par défaut de synchronisation. Quand je l'ai spécifié pour utiliser gevent, tout a fonctionné.

Merci, @jhillhouse92 , je vais essayer.

Je continue à voir des problèmes avec les délais d'attente, @tilgovi. Je vais résoudre ce problème plus demain et publierai une mise à jour avec des informations plus précises. Veuillez garder ce problème ouvert ; vous avez raison de dire qu'il peut y avoir une variété de problèmes, mais le thème général est que les travailleurs de gunicorn (peut-être juste avec la classe de travailleurs de synchronisation, à déterminer) ont des problèmes de délai d'attente lors de l'utilisation de gunicorn avec une application déployée à l'aide d'AWS/ELB. Il y a quelque chose qui ne va pas ici, même si nous n'avons pas isolé le problème exact. Cela vaut la peine de creuser plus loin. Je mettrai à jour demain.

À noter, j'ai rencontré ce problème localement pas dans Docker/AWS/ELB avec la pile ci-dessus que j'ai mentionnée.

J'utilise donc gevent, j'essaie de capturer mes journaux d'accès et j'essaie de déployer mon application à l'aide d'AWS/ELB.

commandes dockerfile :

FROM cortex/base

CMD ["gunicorn", "-w", "8", "-b", "0.0.0.0:5000", "--capture-output", "--enable-stdio-inheritance", "--access-logfile", "-", "--worker-class", "gevent", "-t", "60", "--log-level", "debug", "app:app"]

Je reçois des erreurs OOM folles par rapport au code d'erreur 14, quelles que soient les limites auxquelles j'ai fixé. Quelqu'un d'autre a-t-il vu cela dans le contexte de ce problème ? Auparavant, je pouvais voir les délais d'attente des travailleurs. Avec mes configs actuelles, je ne peux pas reproduire les timeouts/aller aussi loin.

[2017-07-19 18:27:39 +0000] [34] [ERROR] Exception in worker process
Traceback (most recent call last):
  File "/usr/local/lib/python3.5/site-packages/gunicorn/arbiter.py", line 578, in spawn_worker
    worker.init_process()
  File "/usr/local/lib/python3.5/site-packages/gunicorn/workers/ggevent.py", line 190, in init_process
    super(GeventWorker, self).init_process()
  File "/usr/local/lib/python3.5/site-packages/gunicorn/workers/base.py", line 126, in init_process
    self.load_wsgi()
  File "/usr/local/lib/python3.5/site-packages/gunicorn/workers/base.py", line 135, in load_wsgi
    self.wsgi = self.app.wsgi()
  File "/usr/local/lib/python3.5/site-packages/gunicorn/app/base.py", line 67, in wsgi
    self.callable = self.load()
  File "/usr/local/lib/python3.5/site-packages/gunicorn/app/wsgiapp.py", line 65, in load
    return self.load_wsgiapp()
  File "/usr/local/lib/python3.5/site-packages/gunicorn/app/wsgiapp.py", line 52, in load_wsgiapp
    return util.import_app(self.app_uri)
  File "/usr/local/lib/python3.5/site-packages/gunicorn/util.py", line 376, in import_app
    __import__(module)
  File "/code/app/__init__.py", line 2, in <module>
    from flask_alchy import Alchy
  File "/usr/local/lib/python3.5/site-packages/flask_alchy.py", line 8, in <module>
    from flask_sqlalchemy import SQLAlchemy
  File "/usr/local/lib/python3.5/site-packages/flask_sqlalchemy/__init__.py", line 18, in <module>
    import sqlalchemy
  File "/usr/local/lib/python3.5/site-packages/sqlalchemy/__init__.py", line 9, in <module>
    from .sql import (
  File "/usr/local/lib/python3.5/site-packages/sqlalchemy/sql/__init__.py", line 8, in <module>
    from .expression import (
  File "/usr/local/lib/python3.5/site-packages/sqlalchemy/sql/expression.py", line 34, in <module>
    from .functions import func, modifier, FunctionElement, Function
  File "/usr/local/lib/python3.5/site-packages/sqlalchemy/sql/functions.py", line 11, in <module>
    from . import sqltypes, schema
  File "<frozen importlib._bootstrap>", line 969, in _find_and_load
  File "<frozen importlib._bootstrap>", line 958, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 673, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 658, in exec_module
  File "<frozen importlib._bootstrap_external>", line 763, in get_code
  File "<frozen importlib._bootstrap_external>", line 816, in get_data
OSError: [Errno 14] Bad address

Pour réitérer, je ne vois pas cela localement sans docker. Je ne vois pas cela localement avec Docker. Ceci, et les problèmes de délai d'attente, ne deviennent qu'apparemment dans la pile Docker/AWS/ELB (pour moi).

@tilgovi Une chose que j'ai mal faite au départ (comme on peut le voir dans l'extrait que j'ai posté ci-dessus) est que le délai d'attente était mal réglé sur 10 secondes. Après avoir changé cela à 75 secondes, le nombre de délais d'attente des travailleurs a considérablement diminué pour atteindre peut-être quelques secondes par jour. Pour être complet, voici la commande exacte que j'utilise pour démarrer notre application :

gunicorn -k gevent --timeout 90 --keep-alive 75 --paste /etc/jzoo/app.ini "$@"

Le fichier .ini ressemble à ceci :

[DEFAULT]
sqlalchemy.url = postgresql://XXXX

[app:main]
use = egg:jzoo.api.admin

[server:main]
use = egg:gunicorn#main
bind = 0.0.0.0:5000
workers = 4
preload_app = true
loglevel = warning

# Logging configuration
[loggers]
keys = root,sqlalchemy,alembic,jzoo

# .. more logging configuration

La quantité de trafic ne semble pas être un facteur - je vois cela se produire dans notre environnement d'assurance qualité qui ne voit que très peu de trafic.

En regardant à quelle fréquence cela se produit, je me demande si cela pourrait être lié au redémarrage de l'application ?

J'ai un problème un peu similaire. Après quelques investigations, je pense que c'est probablement une erreur de connexion réseau, pas celle de gunicorn.

Voici ma configuration :

  • Le serveur Postgresql s'exécute sur Docker sur EC2. L'image docker est le postgres officiel 9.6.
  • Le serveur d'applications s'exécute sur Docker dans une machine virtuelle en dehors d'EC2. L'image docker est le python 3.6 officiel.
  • Seul le port 5432/tcp est ouvert dans le groupe de sécurité AWS.

Curieusement, la plupart des demandes du serveur d'applications au serveur postgres étaient OK, sauf une. Cette requête semble s'exécuter pour toujours, ce qui fait expirer le travailleur gunicorn.

Le problème est résolu si j'utilise l'application localement.

Le problème est également résolu si je ne dockerise pas le serveur d'applications.

Mon correctif temporel est d'ouvrir toutes les connexions entre le serveur d'applications et le serveur postgres via le paramètre de groupe de sécurité AWS. Maintenant, tout fonctionne à nouveau correctement.

Je suppose qu'il y a un problème de connexion entre le conteneur Python et AWS. Je mettrai à jour après avoir soigneusement examiné le flux de journaux AWS.

Merci!! Changer ELB et le protocole d'instance de HTTP à TCP a très bien fonctionné 👍

Le problème ne semble pas spécifique à AWS, mais à Docker lui-même lorsqu'il est combiné avec Gunicorn. Je le vois aussi avec gevent , du moins dans notre environnement de production.

@tilgovi Voici une application simple pour recréer cette erreur (de temps en temps, vous n'avez pas trouvé le modèle, peut-être) :

app.py :

import falcon


class HelloResource:
    def on_get(self, req, resp):
        resp.media = {'info': 'hello world'}


app = falcon.API()
app.add_route('/', HelloResource())

Fichier Docker :

FROM python:3.6
WORKDIR /code
RUN pip install gunicorn falcon
COPY app.py .
CMD ["gunicorn", "app:app", "--bind", "0.0.0.0:8000"]

Pour courir : docker build -t gunicorn-and-docker . && docker run -p 8000:8000 -it --rm gunicorn-and-docker

Les journaux ressembleront à ceci (au moins pour moi sur macOS Sierra en utilisant Docker 17.06.2-ce-mac27 (19124)):

[2017-09-23 22:31:00 +0000] [1] [INFO] Starting gunicorn 19.7.1
[2017-09-23 22:31:00 +0000] [1] [INFO] Listening at: http://0.0.0.0:8000 (1)
[2017-09-23 22:31:00 +0000] [1] [INFO] Using worker: sync
[2017-09-23 22:31:00 +0000] [9] [INFO] Booting worker with pid: 9
[2017-09-23 23:22:45 +0000] [1] [CRITICAL] WORKER TIMEOUT (pid:9)
[2017-09-23 23:22:45 +0000] [9] [INFO] Worker exiting (pid: 9)
[2017-09-23 23:22:45 +0000] [11] [INFO] Booting worker with pid: 11
[2017-09-23 23:39:46 +0000] [1] [CRITICAL] WORKER TIMEOUT (pid:11)
[2017-09-23 23:39:46 +0000] [11] [INFO] Worker exiting (pid: 11)
[2017-09-23 23:39:46 +0000] [13] [INFO] Booting worker with pid: 13
[2017-09-23 23:41:10 +0000] [1] [CRITICAL] WORKER TIMEOUT (pid:13)
[2017-09-23 23:41:10 +0000] [13] [INFO] Worker exiting (pid: 13)
[2017-09-23 23:41:10 +0000] [15] [INFO] Booting worker with pid: 15
[2017-09-23 23:42:27 +0000] [1] [CRITICAL] WORKER TIMEOUT (pid:15)
[2017-09-23 23:42:27 +0000] [15] [INFO] Worker exiting (pid: 15)
[2017-09-23 23:42:27 +0000] [17] [INFO] Booting worker with pid: 17
[2017-09-23 23:43:44 +0000] [1] [CRITICAL] WORKER TIMEOUT (pid:17)
[2017-09-23 23:43:44 +0000] [17] [INFO] Worker exiting (pid: 17)
[2017-09-23 23:43:44 +0000] [19] [INFO] Booting worker with pid: 19
[2017-09-24 18:37:12 +0000] [1] [CRITICAL] WORKER TIMEOUT (pid:19)
[2017-09-24 18:37:12 +0000] [19] [INFO] Worker exiting (pid: 19)
[2017-09-24 18:37:12 +0000] [21] [INFO] Booting worker with pid: 21
[2017-09-24 19:49:20 +0000] [1] [CRITICAL] WORKER TIMEOUT (pid:21)
[2017-09-24 19:49:20 +0000] [21] [INFO] Worker exiting (pid: 21)
[2017-09-24 19:49:20 +0000] [23] [INFO] Booting worker with pid: 23
[2017-09-24 19:50:37 +0000] [1] [CRITICAL] WORKER TIMEOUT (pid:23)
[2017-09-24 19:50:37 +0000] [23] [INFO] Worker exiting (pid: 23)
[2017-09-24 19:50:37 +0000] [25] [INFO] Booting worker with pid: 25
[2017-09-24 20:25:48 +0000] [1] [CRITICAL] WORKER TIMEOUT (pid:25)
[2017-09-24 20:25:48 +0000] [25] [INFO] Worker exiting (pid: 25)
[2017-09-24 20:25:48 +0000] [27] [INFO] Booting worker with pid: 27

Salut,

J'ai récemment rencontré le même problème.
Dans mon cas (ECS + gunicorn 19.7.1 + Django 1.11.5) j'ai (apparemment) réussi à le résoudre en augmentant simplement la quantité de mémoire dédiée au conteneur dans la définition de la tâche (de 128 à 256 Mo).
Plus d'erreurs pour l'instant. Je signalerai ici si cela se reproduit.

J'ajoute un peu au refrain ici, mais je n'ai pu résoudre ce problème qu'en passant à gevent.

J'ai essayé d'augmenter le délai d'attente à 90 et de rester en vie à 75 avec le travailleur de synchronisation sans succès.

De plus, il est intéressant de noter que mon ELB dans ce scénario ne fait que le transfert de niveau TCP et non HTTP.

Bon, j'ai trouvé des références qui expliquent cela. [1]

Cela pourrait être résolu avec de petits changements du côté de Gunicorn. Si, dans le travailleur de synchronisation, après avoir accepté une nouvelle connexion, nous appelions select() avec un court délai d'attente, nous pourrions gérer ces connexions. Cela pourrait devenir un peu compliqué, surtout avec plusieurs prises d'écoute. Le plus simple serait d'avoir un timeout jusqu'au premier octet. Je ne sais pas non plus comment cela interagirait avec SSL.

[1] https://cloudavail.com/2013/12/21/aws-elb-pre-open-connection-expose-part-1/

Si vous rencontrez ce problème et que vous ne souhaitez pas utiliser gevent/eventlet/asyncio, je vous recommande de passer au thread de travail (fournir le paramètre --threads ).

@tilgovi Le problème semble également exister avec gevent worker, si vous regardez mon exemple ci-dessus.

@jmagnusson votre exemple (de ce commentaire : https://github.com/benoitc/gunicorn/issues/1194#issuecomment-331740187) semble utiliser le travailleur de synchronisation.

[2017-09-23 22:31:00 +0000] [1] [INFO] Utilisation du travailleur : synchroniser

@tilgovi C'est vrai, mais j'ai également vécu cela avec le travailleur gevent , en production. Je vais essayer de trouver du temps pour reproduire avec gevent.

C'est peut-être juste moi (idiot), mais dans le groupe de sécurité EC2 -> règles entrantes, j'ai une règle TCP personnalisée pour le port 5000 (gunicorn ici) pour n'autoriser qu'une seule IP (mon IP : XX.XX.XX.XX /32), changer cela en tout IP aidera.

Je rencontre aussi les ennuis.

[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:03 +0800] [24358] [INFO] worker pid 24358 notify
[2018-01-02 16:38:04 +0800] [24358] [INFO] worker pid 24358 notify
[2018-01-02 16:38:05 +0800] [24358] [INFO] worker pid 24358 notify
[2018-01-02 16:38:06 +0800] [24358] [INFO] worker pid 24358 notify
[2018-01-02 16:38:07 +0800] [24358] [INFO] worker pid 24358 notify
[2018-01-02 16:38:08 +0800] [24358] [INFO] worker pid 24358 notify
[2018-01-02 16:38:09 +0800] [24358] [INFO] worker pid 24358 notify
[2018-01-02 16:38:10 +0800] [24358] [INFO] worker pid 24358 notify
[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:38:41 +0800] [24381] [INFO] worker pid 24381 notify
[2018-01-02 16:38:42 +0800] [24381] [INFO] worker pid 24381 notify
[2018-01-02 16:38:43 +0800] [24381] [INFO] worker pid 24381 notify
[2018-01-02 16:38:44 +0800] [24381] [INFO] worker pid 24381 notify
[2018-01-02 16:38:45 +0800] [24381] [INFO] worker pid 24381 notify
[2018-01-02 16:38:46 +0800] [24381] [INFO] worker pid 24381 notify
[2018-01-02 16:38:47 +0800] [24381] [INFO] worker pid 24381 notify
......
[2018-01-02 16:48:20 +0800] [24381] [INFO] worker pid 24381 notify
[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. 

J'ai ajouté le journal de débogage worker pid {WORKER_PID} notify .

D'après le journal de débogage,

  1. Ce n'est que si le processus de travail reçoit une demande que la notification ne se poursuivra pas. Ainsi, qu'il y ait des demandes ou non, le maître tuera le processus de travail après 30 secondes.
  2. Une fois la première demande fermée, j'ai envoyé la deuxième demande tout de suite, mais la deuxième demande est bloquée et il n'y a pas de réponse. Lorsque le délai d'attente de 30s a atteint, le processus de travail a été tué et le nouveau processus de travail répondait à la deuxième demande. Ensuite, le serveur a été à nouveau bloqué.
  3. Lorsque le processus de travail a été suspendu, il ne recevrait pas le signal du maître, tel que SIGTERM . Lorsque le délai d'attente gracieux atteint, le maître le tuerait par SIGKILL coercitive.
Python: 3.6.3
Gevent: 1.2.2
Gunicorn: 19.7.1
RUN CMD: gunicorn --worker-class gevent --log-level debug --bind 0.0.0.0:8080 app

AVIS : Lorsque j'utilise eventlet comme travailleur, tout va bien.

Je vais clore ce sujet car je pense qu'il est un peu dépassé. Pour autant que je puisse le déterminer, le comportement observé est dû au fait que AWS Classic Load Balancers effectue une optimisation avant ouverture. Cette optimisation n'est effectuée que par les Classic Load Balancers, selon la documentation sur le fonctionnement de l'équilibrage de charge . Le passage aux équilibreurs de charge d'application devrait résoudre le problème. De plus, comme documenté dans cet article de blog , il est possible de demander à AWS de désactiver l'optimisation de pré-ouverture ou d'augmenter le délai d'expiration du travailleur pour Gunicorn.

@tilgovi FWIW J'ai vu ça avec ALB. Je n'ai jamais utilisé d'équilibreurs de charge classiques.

@tilgovi J'ai moi aussi observé cela à plusieurs reprises dans des environnements ALB uniquement, n'ayant jamais utilisé le classique. Même avec des ajustements de délai d'expiration des travailleurs, nous avons continué à voir cela.

@tilgovi J'ai rencontré ça. Je n'ai jamais utilisé AWS.

Quelqu'un doit alors aider à reproduire cela et essayer de le déboguer. Je ne peux pas le reproduire avec ALB et je ne vois pas comment le reproduire en dehors d'AWS.

@xgfone, vous voudrez peut-être ouvrir votre propre numéro, le titre de ce numéro est "docker + AWS"

Quelqu'un a-t-il vécu cela avec les équilibreurs de charge AWS mais sans Docker ? Je suis un peu confus, je dois admettre :)

Mon impression était que le problème était vraiment plus lié à Docker - au moins j'ai eu exactement les mêmes problèmes en exécutant plusieurs travailleurs de synchronisation gunicorn dans Docker sur ma machine locale.

Cette configuration a bien fonctionné sans Docker sur les machines Ubuntu et RHEL, à la fois bare metal et virtualisées dans Digital Ocean :

workers = 2
worker_class = 'sync'
worker_connections = 1000
timeout = 30
keepalive = 2

À l'intérieur de Docker (également RHEL, tout le reste identique), les travailleurs ont toujours dépassé le délai d'expiration et ont continué à redémarrer de manière permanente. En prenant les recommandations de ce fil, je suis passé à ceci, qui fonctionne parfaitement bien :

workers = 1
threads = 8
worker_class = 'sync'
worker_connections = 1000
timeout = 30
keepalive = 2

Si vous pensez que ce n'est pas lié à ce fil, je suis heureux de le supprimer d'ici et de le mettre ailleurs ;-)

Meilleur, Boris

@tilgovi

Cette erreur se produit dans le fichier arbiter.py, murder_workers . La fonction murder_workers est invoquée lorsque le SIG_QUEUE est vide (par exemple en attendant des signaux).

Il vérifierait ensuite si le délai d'attente a été atteint chaque seconde. Le temps restant à vivre était toujours de 1 sec ou 0 sec car le gevent worker est dans une boucle infinie contrôlée tandis que self.alive invoquait self.notify qui met à jour un fichier. Les mises à jour du fichier indiquent comment gunicorn vérifie la dernière heure active.

Ainsi, la seule façon dont la vérification de la durée de vie dans la fonction murder_workers échoue (par exemple, dit qu'elle est restée inactive trop longtemps) est de modifier la propriété gevent alive. Les méthodes suivantes contrôlent cela :

handle_quit
handle_request (si le nombre maximum de requêtes a été reçu, par défaut c'est 2^64 bits de nombre de requêtes ou 2^32 si OS 32 bits)
changed (appelé depuis le rechargeur si un fichier a été modifié)
handle_exit
handle_abort

Ces méthodes sont invoquées à partir de signaux

handle_quit - SIGNE, SIGNE
handle_exit - SIGTERM
handle_abort - SIGABRT

Ainsi, il y a 2 problèmes possibles que je vois:

  1. La méthode notify n'est pas en mesure de mettre à jour le fichier pendant sa boucle
  2. Un signal est mal envoyé

Je pense que la cause la plus probable est la 2ème. La principale source de signaux se trouve dans le fichier de l'arbitre et est déclenchée par ces exceptions :

  • StopIteration
  • KeyboardInterrupt
  • HaltServer
  • Exception (exception non gérée)

Je pense que l'exception StopIteration est probablement le coupable déclenché dans le fichier async.py à req = six.next(parser) . Il semble que cette méthode suivante appelle simplement parser.next().

Parser.next() lève une exception StopIteration aux 2 conditions suivantes :

1. If the message indicates it should close:
    1. http Connection close (and keep-alive false)
    2. WSGI - request method not HEAD, response_length is none, and status code is > 200 (but not 204, or 304)
2. If self.mesg (Request message) is falsey

Je ne sais pas exactement ce qui pourrait causer cela involontairement, mais sur 62 commentaires avec ce problème vu dans plusieurs applications et environnements, je pense que cela vaut la peine d'étudier plus avant et recommande de le rouvrir ou si nous n'aimons pas le titre , créent un nouveau problème mondial avec des travailleurs qui expirent de manière critique.

Je vais rouvrir ceci et essayer de tester ces combinaisons :

  • Docker local
  • Docker AWS avec Classic Load Balancer
  • Docker AWS avec équilibreur de charge d'application

Si quelqu'un veut créer un dépôt qui peut reproduire cela, ce serait utile, mais je peux probablement le faire ce week-end.

J'ai ce problème et je n'utilise pas AWS.
Ma configuration est NGINX -> conteneur Docker (Gunicorn avec gevent workers + Django). J'utilise les délais d'attente par défaut du Gunicorn.

Des conseils ?

Merci.

Salut @davidmir ,
J'ai eu le même problème, changer le type de travailleur n'a pas aidé. Le passage à un seul travailleur de synchronisation avec plusieurs threads a fait l'affaire pour moi :

workers = 1
threads = 8
worker_class = 'sync'
worker_connections = 1000
timeout = 30
keepalive = 2

Meilleur, Boris

Bien que cela soit mentionné ci-dessus, pour clarifier mon propre débogage de ce problème, certains d'entre eux sont des erreurs de mémoire insuffisante; surtout s'il est résolu en changeant le compte à rebours des travailleurs à 1.

C'est particulièrement problématique sur Docker si vous avez quelque chose comme ça dans votre configuration :

workers = multiprocessing.cpu_count() * 2 + 1

Mais limitent la mémoire disponible pour le conteneur ; le travailleur synchrone démarrera plusieurs interpréteurs python potentiellement lourds. Notez que le nombre de processeurs est basé sur le nombre total de processeurs de la machine, et non sur ce que vous avez configuré pour le conteneur Docker ; si vous utilisez un conteneur limité, vous devez plutôt baser le nombre de travailleurs sur celui-ci.

Bien que cela varie d'une application à l'autre, ma règle empirique est de 256 Mo par travailleur dans une configuration allégée et de 512 pour être sûr.

Face au même problème en utilisant Classic ELB HTTPS => HTTP Gunicorn Sync Workers

Comme d'autres l'ont mentionné, la solution la plus simple consistait à utiliser l'argument -k gevent au lieu du travailleur de synchronisation par défaut.

Nous avons vu ce même problème surgir à nouveau pour un tout nouveau conteneur Docker (hébergé dans ECS derrière ALB), et avons trouvé une solution entièrement différente (mais avec le recul, aurait dû être évidente) : allouer plus de mémoire au conteneur dans CloudFormation modèle.

Nous avons souffert de ce problème l'année dernière et n'avons jamais vraiment trouvé de cause première, mais ce soir, je l'ai repéré sur un nouveau conteneur et j'ai remarqué que le conteneur consommait toute la mémoire que nous avions allouée. Dès que j'ai doublé l'allocation, les conteneurs ont cessé de générer cette erreur (avant même que j'alloue plus qu'il n'en consommerait finalement):
https://github.com/hackoregon/civic-devops/issues/157

Face à un problème similaire ici. le code est aussi simple que

while true:
      sleep(10)

peut entraîner la mort d'un travailleur (sans ce code, notre déploiement est normal)
c'est très déroutant, b/c sleep devrait déjà envoyer un battement de cœur.

ont également déjà changé pour gevent, n'a pas aidé. Je me demande si quelqu'un a une idée ?

exemple de sortie :
[2018-06-16 16:00:16 +0000] [136] [CRITICAL] WORKER TIMEOUT (pid:521) [2018-06-16 16:00:16 +0000] [136] [CRITICAL] WORKER TIMEOUT (pid:522) [2018-06-16 16:00:16 +0000] [136] [CRITICAL] WORKER TIMEOUT (pid:523) [2018-06-16 16:00:16 +0000] [136] [CRITICAL] WORKER TIMEOUT (pid:524) [2018-06-16 16:00:16 +0000] [136] [CRITICAL] WORKER TIMEOUT (pid:525) [2018-06-16 16:00:16 +0000] [524] [INFO] Worker exiting (pid: 524) [2018-06-16 16:00:16 +0000] [521] [INFO] Worker exiting (pid: 521) [2018-06-16 16:00:16 +0000] [523] [INFO] Worker exiting (pid: 523) [2018-06-16 16:00:16 +0000] [522] [INFO] Worker exiting (pid: 522) [2018-06-16 16:00:16 +0000] [525] [INFO] Worker exiting (pid: 525) [2018-06-16 16:00:17 +0000] [531] [INFO] Booting worker with pid: 531 /usr/local/lib/python3.6/site-packages/gunicorn/workers/ggevent.py:65: MonkeyPatchWarning: Monkey-patching ssl after ssl has already been imported may lead to errors, including RecursionError on Python 3.6. Please monkey-patch earlier. See https://github.com/gevent/gevent/issues/1016 monkey.patch_all(subprocess=True) [2018-06-16 16:00:17 +0000] [136] [DEBUG] 1 workers [2018-06-16 16:00:17 +0000] [532] [INFO] Booting worker with pid: 532 [2018-06-16 16:00:17 +0000] [533] [INFO] Booting worker with pid: 533 /usr/local/lib/python3.6/site-packages/gunicorn/workers/ggevent.py:65: MonkeyPatchWarning: Monkey-patching ssl after ssl has already been imported may lead to errors, including RecursionError on Python 3.6. Please monkey-patch earlier. See https://github.com/gevent/gevent/issues/1016 monkey.patch_all(subprocess=True) [2018-06-16 16:00:17 +0000] [534] [INFO] Booting worker with pid: 534 /usr/local/lib/python3.6/site-packages/gunicorn/workers/ggevent.py:65: MonkeyPatchWarning: Monkey-patching ssl after ssl has already been imported may lead to errors, including RecursionError on Python 3.6. Please monkey-patch earlier. See https://github.com/gevent/gevent/issues/1016 monkey.patch_all(subprocess=True) [2018-06-16 16:00:17 +0000] [535] [INFO] Booting worker with pid: 535 [2018-06-16 16:00:17 +0000] [136] [DEBUG] 5 workers

Désolé de brouiller les cartes ici, mais je voulais juste partager mon expérience, ma pile est de HTTP ELB > Nginx > gunicorn/gevent on EC2 , les processus s'exécutent avec circusd

Le problème que j'ai trouvé était qu'après avoir instrumenté mon application Django avec Elastic-apm, mes vérifications de l'état HTTP commenceraient à échouer presque immédiatement et gunicorn deviendrait insensible après quelques secondes.

J'ai essayé quelques points wrk repère locaux de

Je n'ai pas remarqué d'utilisation étrange de la mémoire sur valgrind, généralement environ 4 Mo pour gunicorn et 40 Mo par travailleur

Quoi qu'il en soit, la mise gunicorn 19.6.0 > 19.9.0 jour de gevent 1.2.2 > 1.3.6 me donne à nouveau un bilan de santé ELB solide et ~ 300 rps localement. Je n'avais délibérément pas mis à jour gunicorn/gevent jusqu'à ce que j'aie une connexion APM en place, il semble que cela ait suscité un certain heureux hasard. La mise à jour de gevent a donné le plus grand coup de pouce, c'est compréhensible, mais la mise à jour de gunicorn a semblé ajouter environ 10% supplémentaires.

Je n'ai pas encore examiné les changelogs en détail, peut-être que les responsables peuvent faire la lumière sur la cause la plus probable ?

Quoi qu'il en soit, la mise à jour de gunicorn 19.6.0 > 19.9.0 et gevent 1.2.2 > 1.3.6 me donne à nouveau un bilan de santé ELB solide et ~ 300 rps localement .... La mise à jour de gevent a donné le plus grand coup de pouce

Wow, c'est plutôt cool !

problème de clôture. aucune activité depuis un moment.

FWIW, j'ai toujours ce problème @benoitc :-\

Django 2.1.5
gunicorne 19.8.1
événement 1.2.2
AKS 1.15.7 avec 5 nœuds (B2 standard - 2 vcores et 2 Go de mémoire)
3 pods/conteneurs docker, chacun ayant :

    spec:
      containers:
        - name: web-container
          command: ["newrelic-admin"]
          args: [
              "run-program",
              "gunicorn",
              "--limit-request-field_size=16380", # limit also specified in nginx
              "--workers=3", # (2 x vcpu) + 1. vcpu < limit defined in resources
              "-k=gevent",
              "-b=0.0.0.0:8000",
              "ourapp.wsgi",
              "--timeout 60",
              "--log-level=debug",
            ]
          resources:
            requests:
              memory: "200Mi"
              cpu: "250m"
            limits:
              memory: "3000Mi"
              cpu: "2000m"

Même problème ici avec EKS, Nginx et un NLB.

@salmicrosoft @sinkr OK, mais veuillez ouvrir un nouveau problème et fournir tous les journaux dont vous disposez qui pourraient nous aider à comprendre ce qui se passe. Aussi qu'est-ce que votre application? Avez-vous une longue demande?

J'ai eu le même problème sur l'ECS Fargate, mais il était lié à des paramètres de keepalive/timeout incorrects dans Docker/gunicorn.conf.py, c'était
keepalive (non défini)
délai d'attente=2

Avant de le réparer, cela fonctionnait bien avec un conteneur exécuté localement, mais échouait sur l'ECS Fargate, maintenant cela fonctionne correctement sur les deux environnements.

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