Gunicorn: Os workers de sincronização Gunicorn expiram no docker + AWS

Criado em 29 jan. 2016  ·  78Comentários  ·  Fonte: benoitc/gunicorn

Usando o gunicorn 19.4.5 dentro de uma imagem docker, que está em execução no Ubuntu 14.04 LTS na AWS, vejo tempos limites de trabalho constantes ao executar com> 1 trabalhador de sincronização e o período de tempo limite de 30s padrão. Isso pode estar relacionado a # 588 ou # 942, embora esta seja uma versão significativamente mais recente do gunicorn, então eu não poderia dizer com certeza.

Evidências circunstanciais ao longo de várias execuções parecem sugerir que um dos trabalhadores não foi afetado e são apenas os N-1 restantes que continuam falhando e reiniciando. No entanto, só consegui alguns pontos de dados que sugerem isso, então não tome isso como um sinal forte.

Aqui estão as coisas que verifiquei:

  • Os problemas acontecem fora do docker ou ao usar a mesma imagem do docker, mas não na AWS?
    Não, só consegui replicar o problema com o docker na AWS.
  • O aplicativo leva mais de 30 segundos para inicializar?
    Não, o aplicativo termina a inicialização em menos de 1 segundo.
  • O aplicativo recebe uma solicitação que o faz travar?
    O problema apareceu sem que nenhuma solicitação fosse feita ao aplicativo.
  • O aplicativo tem código de inicialização corrompido que confunde o gunicorn?
    O problema surgiu ao executar o gunicorn na mesma configuração (com> 1 trabalho de sincronização), mas com um aplicativo diferente. Este novo aplicativo é executado sem problemas no gunicorn ao usar os trabalhadores gevent.
  • O sistema de arquivos do docker não consegue atualizar o ctime?
    Veja o log abaixo - o ctime geralmente parece avançar bem. O sistema de arquivos do Docker não permite stat -L em arquivos excluídos, mas evitar que o gunicorn desvincule o arquivo também resulta em stat -L mostrando que ctime está sendo atualizado normalmente.

Eu adicionei algum código a workertmp.py para registrar o ctime de leitura em cada verificação, e aqui está um desses registros (intercalado entre todos os trabalhadores):

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

Comentários muito úteis

Tente usar os trabalhadores gevent , isso resolveu o problema para mim.

Todos 78 comentários

hrmmm pelo log acima, posso ver que o tempo nunca muda. eu vou verificar

Obrigado, Eu agradeço!

Eu posso ser afetado por este bug.

Estou executando o gunicorn dentro de uma imagem do Docker no AWS (Elastic Beanstalk + EC2 Container Service).
Existem tempos limites de trabalho constantes que começam a acontecer quase imediatamente após a inicialização e apenas ao executar a imagem Docker no AWS.
A mesma solicitação HTTP leva às vezes alguns ms, às vezes 20-30 segundos. Não importa se é para uma página inexistente, uma página de string "Hello world" simples não autenticada ou uma página que busca registros de um banco de dados.

Detalhes adicionais :

  • Versões do Gunicorn : 19.5.0 e 19.6.0.
  • Imagem base do Docker : python: 3.4 ( SO : Debian Jessie)
  • Versão do Docker : 1.9.1 (gerenciado pelo Amazon ECS), SO : Amazon Linux AMI 2016.03 (gerenciado pelo Amazon EB).
  • Framework de aplicativos da Web : Django versões 1.9.6 e 1.9.7.

Ambientes _não_ afetados :

  • Máquina local , _inside_ e _outside_ um contêiner Docker. SO : Ubuntu 16.04 LTS, Docker : 1.11.2.
  • Heroku ( SO : Ubuntu 14.04 LTS)

Logs de contêineres da 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)
(...)

`

Obrigado.

Eu também estou vendo isso. Minha suspeita é o Elastic Load Balancer. Costumávamos usar paste em uma empresa anterior e isso estava causando problemas com o ELB. Eu acredito que ele reutiliza as conexões de alguma forma e isso estava causando problemas em paste .

Agora estou em um novo emprego em que usamos gunicorn e estava tudo bem até que começamos a colocar o servidor atrás de um ELB, o webapp agora muitas vezes não responde e aparentemente trava.

Tente usar os trabalhadores gevent , isso resolveu o problema para mim.

Então, isso é um problema com o ELB mantendo as conexões ativas e prendendo o trabalhador de sincronização? Isso me pareceria muito estranho, já que sinalizamos deliberadamente que a conexão deve ser fechada com o trabalhador de sincronização: https://github.com/benoitc/gunicorn/blob/master/gunicorn/workers/sync.py#L168

Podemos fechar a conexão deliberadamente, no entanto. Se alguém quiser testar mover a chamada client.close() para ser incondicional, esse pode ser um teste interessante: https://github.com/benoitc/gunicorn/blob/master/gunicorn/workers/sync.py#L199

Você também pode ter certeza de que o tempo limite de inatividade no ELB é menor do que o tempo limite do trabalhador, como uma verificação rápida de sanidade se essa é a causa do problema: http://docs.aws.amazon.com/elasticloadbalancing/latest/ classic / config-idle-timeout.html

@tilgovi a coisa do gevent . Mas novamente, quem sabe..

isso acontece apenas atrás do ELB e se o protocolo HTTP ou HTTPS estiver definido no ELB.
Se você alterar o protocolo para TCP ou SSL, o problema desaparecerá.
Alguém sabe como consertar ainda usando os trabalhos de sincronização? Usei a correção que descrevi (TCP em vez de HTTP) até agora, quando vou monitorar os logs de acesso e ver o cabeçalho X-Forwarded-For, que está habilitado apenas para HTTP / HTTPS em ELB :)

Estranho, só para ter certeza de que estamos na mesma página, isso significa que existe algum tipo de otimização ao usar a opção HTTP / HTTPS no ELB? E essa otimização está causando problemas com os trabalhos de sincronização?

@ecs Eu acho que no caso do balanceador de carga HTTP / HTTPS, reutilize a mesma conexão TCP, que é mantida pelo ELB ativo por muito tempo - algum tipo disso. Mas isso não explica por que o gevent worker funciona bem ... (embora eu não tenha testado o gevent ainda, apenas leia esses comentários)

A propósito, certamente há muitos fatores (versão do gunicorn, classe de trabalho, dentro do docker ou não, protocolo ELB) que podem influenciar, então seria ótimo se alguém testasse e confirmasse que o protocolo TCP no ELB funciona ao contrário do HTTP. Estou testando no docker hospedado no Ubuntu 14.04 e gunicorn versão 19.3.0

Eu tenho o mesmo problema:
[2016-10-03 12:13:17 +0000] [6] [CRÍTICO] TEMPO LIMITE DO TRABALHADOR (pid: 16)
[2016-10-03 12:13:17 +0000] [16] [INFO] Trabalhador saindo (pid: 16)
[2016-10-03 12:13:17 +0000] [6] [CRÍTICO] TEMPO LIMITE DO TRABALHADOR (pid: 20)
[2016-10-03 12:13:17 +0000] [20] [INFO] Trabalhador saindo (pid: 20)
[2016-10-03 12:13:17 +0000] [33] [INFO] Inicializando trabalhador com pid: 33

Minha configuração.

Estou usando o kube-aws para configurar um cluster kubernetes com core-os no AWS: https://github.com/coreos/coreos-kubernetes/tree/master/multi-node/aws

Eu tenho um aplicativo python usando gunicorn e trabalhos de sincronização. O serviço para eles usa um balanceador de carga HTTPS com o certificado de meus sites. Todos os workers são considerados expirados após o tempo limite padrão de 30s, ao que parece. Eles são todos reiniciados eventualmente. O Kubernetes eventualmente reinicia o contêiner quando ele sai. Essas reinicializações acontecem continuamente. Alguém mencionou acima que o gevent resolve o problema. Eu posso tentar fazer isso, mas eu realmente gostaria de entender por que isso está acontecendo.

Também estamos vendo esse problema. Vou tentar postar mais detalhes quando tiver oportunidade. Ele está relacionado ao trabalhador de sincronização, pois a mudança para o gevent realmente resolve o problema. Isso está na AWS com ECS e ELB.

Tive o mesmo problema estranho com um de nossos aplicativos. Mudar os ouvintes de HTTP para tcp realmente resolve o problema.

Alguém pode me fornecer uma maneira passo a passo de reproduzir o problema? (etapa de configuração e tal) Ou pelo menos me indique uma maneira simples de configurar esse ambiente :) Vou dar uma olhada nele esta semana.

Depender de HTTP para esse balanceador geralmente requer o manuseio do keep-alive behind, (exceto para tcp), portanto, qualquer coisa que use um trabalhador de sincronização pode ser um problema até que o trabalhador de sincronização seja atualizado para seu suporte.

De qualquer forma, me avise.

Basta configurar um aplicativo Flask básico e executá-lo com gunicorn com trabalhos de sincronização dentro do docker no AWS, com balanceamento de carga HTTP e a configuração acima:

Usando o gunicorn 19.4.5 dentro de uma imagem docker, que está em execução no Ubuntu 14.04 LTS na AWS, vejo tempos limites de trabalho constantes ao executar com> 1 trabalhador de sincronização e o período de tempo limite de 30s padrão.

Você não precisa fazer nenhuma solicitação ao aplicativo, apenas monitore os logs e você verá os workers expirando.

  • Posso confirmar esse comportamento, bem como a abordagem básica para reproduzi-lo.

    • O comportamento não se limita ao Docker, mas sim ao trabalhador de sincronização / configuração de manutenção de atividade, portanto, você pode considerar alterar o título ...

  • Eu modifiquei a configuração de keepalive para seguir o que está descrito aqui: https://serverfault.com/questions/782022/keepalive-setting-for-gunicorn-behind-elb-without-nginx/ (a parte mais interessante é a citação da documentação do AWS ELB) e descobrimos que o servidor não exibe mais esse comportamento.
  • Além disso, também mudei para a classe de trabalho gthread e achei o resultado muito aceitável até agora.

Atualmente, estou usando gevent workers com um período de tempo limite de 65s (o tempo limite do AWS ELB é 60s, AFAIK). Ainda encontro erros 504 às vezes, mesmo quando apenas um cliente faz solicitações, com 1 solicitação em andamento por vez, mas ainda não consegui identificar o motivo.

@ obi1kenobi Você tentou aumentar o keepalive para além da opção de tempo limite do ELB?

@lenucksi o keepalive já é maior do que o tempo limite ELB em 5s - espero que os relógios dos servidores não

Eu também encontrei esse problema ao executar o gunicorn 19.6 dentro de um contêiner do Docker em uma instância EC2 atrás de um ELB (usando o protocolo HTTP padrão para proxy reverso para a instância EC2).

Como sugerido anteriormente, definir a classe de trabalho como gevent resolveu esse problema para mim (onde antes eu estava usando a classe de trabalho padrão sync ).

Vou tentar documentar um exemplo mínimo para reproduzir o problema.

Para corroborar o que outros disseram, o ELB parece estar abrindo uma conexão com a instância EC2 e mantendo-a aberta de uma forma que bloqueia o gunicorn de lidar com solicitações adicionais.

Quando essa conexão mantida aberta termina devido ao gunicorn ter atingido o tempo limite da solicitação do ELB, todas as solicitações pendentes enfileiradas atrás dele também falham (incluindo a verificação de integridade do ELB, fazendo com que a instância seja removida do ELB, tornando isso mais difícil de depurar; )).

Este sintoma sugere que esta é uma duplicata do que foi observado na edição anterior que não está relacionada ao Docker: https://github.com/benoitc/gunicorn/issues/588

@jelis Você sabe se isso está relacionado a alguma configuração do kubernetes? O seu problema foi resolvido?

Também estou em um ELB com terminação SSL. Estou vendo isso em meus 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

Atualização - acabei de mudar de gunicorn para gevent (http://flask.pocoo.org/docs/0.12/deploying/wsgi-standalone/#gevent) e o problema foi resolvido. Isso é uma referência ao meu comentário acima https://github.com/benoitc/gunicorn/issues/1194#issuecomment -283269046

Venho martelando nesse assunto há alguns dias. As notas de todos aqui são fantásticas e estão nos dando uma série de caminhos para buscar soluções / soluções alternativas / atenuações. (o registro do meu trabalho está no bug que estamos rastreando aqui )

Eu apenas tentei usar o gevent com um aumento na contagem de trabalhadores e isso não nos ajudou em nada - na verdade, fez com que parecesse pior - todos os cinco trabalhadores do gevent morreram ao mesmo tempo, o que é um novo comportamento de o que li acima:

[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

Isso é provavelmente alguma bagunça da minha parte, e não era o mesmo comportamento de uma das minhas contrapartes de projeto (com uma base de código semelhante, mas não idêntica em uma implantação AWS / CloudFormation / ALB / ECS quase idêntica). No entanto, decidi relatá-lo caso inspire novos insights sobre as interações entre ALB, ECS, Docker e gunicorn.

Eu tenho uma configuração semelhante (convox executando ELB-> ECS Docker Container-> Gunicorn-> Django) e posso confirmar que as seguintes alterações de configuração parecem ter ajudado:

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

Eu defino meu tempo limite inativo ELB para 60 segundos.

Antes de alterar essas configurações, eu estava usando os padrões de keepalive, timeout e sync worker.

Curiosamente, esta edição começou a ser exibida às 4h UTC do dia 10 de abril. O aplicativo estava funcionando bem sem nenhuma alteração desde a quinta-feira anterior.

apenas empilhando, sem docker, mas a instância aws nua estava tendo o mesmo problema atrás de um ELB. funciona NP no osx, mas o ubuntu16 com o mesmo problema ELB apareceu. gevent classe de trabalhador

@erikcw parece ter encontrado essa solução para funcionar. Eu gostaria de encerrar este problema. Se alguém puder reproduzir isso depois de aumentar o tempo limite do trabalhador Gunicorn e o tempo limite de manutenção de atividade, diga isso.

Como alternativa, diminua o tempo limite de inatividade para ELB.

Um cliente em estado selvagem (ou um cliente nefasto) não poderia agir como o ELB e causar o mesmo problema?

@ six8 sim. ELB também não o protege disso. A documentação discute isso: http://docs.gunicorn.org/en/latest/design.html#choosing -a-worker-type

Algumas pessoas não se importam com essa ameaça e querem apenas implantar o Gunicorn, na borda ou atrás de um ELB. O problema discutido aqui são os tempos limite do trabalhador causados ​​pelo próprio ELB. Eu gostaria de fornecer a configuração recomendada que faz o gunicorn funcionar por trás do ELB com trabalhos de sincronização e sem um proxy reverso adicional.

Eu tentei a solução de @erikcw também alterando a invocação do gunicorn para:

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

Infelizmente, isso não ajuda:

[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)

Tenho um aplicativo em execução no ECS por trás de um ALB com trabalhos de sincronização Gunicorn. Eu não vi nenhum problema ainda.

Qualquer pessoa pode fornecer uma implantação reproduzível?

empilhando, também. vendo este problema usando Kubernetes na AWS com ELB. Atualmente temos 8 trabalhadores em execução. Por https://serverfault.com/questions/782022/keepalive-setting-for-gunicorn-behind-elb-without-nginx/ , vamos aumentar keepalive e, de acordo com este tópico, vamos tentar para usar gevent workers em seu lugar. Mas agora, o que está falhando são alguns testes de desempenho para chamadas de API que não deveriam estar bloqueando / causando tempo limite por conta própria. gostaria de saber o que está acontecendo aqui com sync trabalhadores. Mesmo se conseguirmos fazer isso funcionar de acordo com algumas das boas diretrizes neste tópico, gostaríamos de ter um pouco mais de confiança sobre o que está acontecendo antes de implantar para produção.

Definir a classe --worker para --worker-class gevent funcionou para mim. Obrigado pelos comentários e ajuda!

@wichert, isso é muito estranho. Com o trabalhador gevent, os trabalhadores devem notificar o árbitro de sua vida em um greenlet separado de quaisquer conexões. Sua configuração de keep-alive não deve afetar isso de forma alguma. Algo está errado com seu aplicativo, de forma que o gevent não está funcionando conforme projetado, ou algo na configuração é problemático que pode ser comum a esses outros cenários.

Por favor, todos neste tópico, forneçam um aplicativo que reproduza este problema. Eu não fui capaz de reproduzi-lo. Sem etapas para reproduzir, estou tentado a encerrar. Há uma mistura de recomendações e talvez questões muito diferentes enterradas nesses comentários. É difícil saber o que fazer com esse problema.

@tilgovi Eu tive esse problema ao não especificar a classe de trabalho a ser gevent (por exemplo, usando o trabalhador de sincronização padrão). Minha configuração é virtualenv usando pypy3 (PyPy 5.8.0-beta0), falcon 1.2, etc (entendendo que Falcon não é oficialmente compatível com pypy3). Eu usei o cookiecutter de https://github.com/7ideas/cookiecutter-falcon e atualizei para todos os pacotes mais recentes e ao tentar carregar o sample_resource no navegador e acertá-lo várias vezes com httpie veria intermitentemente o erro de falha do trabalhador ( por exemplo, a solicitação seria atrasada e eu veria o erro; se eu não cancelasse a solicitação, ele acabaria respondendo). Isso só aconteceu com a classe de trabalho de sincronização padrão. Quando eu especifiquei para usar gevent, tudo funcionou.

Obrigado, @ jhillhouse92 , vou tentar.

Continuo a ver problemas com tempos limite, @tilgovi. Estarei solucionando mais isso amanhã e postarei uma atualização com informações mais precisas. Por favor, mantenha este problema aberto; você está certo de que pode haver uma variedade de problemas acontecendo, mas o tema geral é que os trabalhadores gunicorn (talvez apenas com a classe de trabalho de sincronização, tbd) estão tendo problemas de tempo limite ao usar o gunicorn com um aplicativo implantado usando AWS / ELB. Há algo errado aqui, mesmo que não tenhamos isolado o problema exato. Vale a pena pesquisar mais. Vou atualizar amanhã.

Vale a pena notar que tive esse problema localmente, não dentro do Docker / AWS / ELB com a pilha acima que mencionei.

Portanto, estou usando gevent, tentando capturar meus logs de acesso e tentando implantar meu aplicativo usando AWS / ELB.

Comandos 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"]

Estou recebendo erros loucos de OOM em relação ao código de erro 14, independentemente de como eu defini os limites. Alguém mais viu isso no contexto deste problema? Anteriormente, eu conseguia ver os tempos limite do trabalhador. Com minhas configurações atuais, não consigo reproduzir os tempos limite / chegar tão longe.

[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

Para reiterar, não vejo isso localmente sem o docker. Não vejo isso localmente com o Docker. Isso, e os problemas de tempo limite, só aparecem aparentemente na pilha Docker / AWS / ELB (para mim).

@tilgovi Uma coisa que eu fiz de errado inicialmente (como pode ser visto no trecho que postei acima) é que o tempo limite foi definido incorretamente para 10 segundos. Depois de mudar isso para 75 segundos, o número de tempos limite do trabalhador caiu significativamente para talvez alguns por dia. Para completar, este é o comando exato que estou usando para iniciar nosso aplicativo:

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

O arquivo .ini tem a seguinte aparência:

[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

A quantidade de tráfego não parece ser um fator - vejo isso acontecendo em nosso ambiente de controle de qualidade, que vê muito pouco tráfego.

Observando a frequência com que isso acontece, fico me perguntando se isso pode estar relacionado a reinicializações de aplicativos.

Eu tenho um problema semelhante. Depois de algumas investigações, acho que provavelmente é um erro de conexão de rede, não do gunicorn.

Esta é minha configuração:

  • O servidor Postgresql é executado no Docker no EC2. A imagem do docker é o postgres oficial 9.6.
  • O servidor de aplicativos é executado no Docker em uma VM fora do EC2. A imagem docker é o python 3.6 oficial.
  • Apenas a porta 5432 / tcp é aberta no grupo de segurança AWS.

Curiosamente, a maioria das solicitações do servidor de aplicativos para o servidor postgres estava OK, exceto uma. Essa consulta parece ser executada para sempre, o que expira o trabalho do gunicorn.

O problema desaparece se eu usar o aplicativo localmente.

O problema também desaparece se eu não encaixar o servidor de aplicativos.

Minha correção temporal é abrir todas as conexões entre o servidor de aplicativos e o servidor postgres por meio da configuração do grupo de segurança da AWS. Agora tudo funciona corretamente novamente.

Meu palpite é que há um problema de conexão entre o contêiner Python e a AWS. Vou atualizar depois de examinar o fluxo de log da AWS completamente.

Obrigado!! Alterar o protocolo ELB e de instância de HTTP para TCP funcionou bem 👍

O problema não parece específico da AWS, mas do próprio Docker quando combinado com o Gunicorn. Também vejo isso com gevent , pelo menos em nosso ambiente de produção.

@tilgovi Este é um aplicativo simples para recriar esse erro (de vez em quando, não encontrei o padrão, talvez você possa):

app.py:

import falcon


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


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

Dockerfile:

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

Para executar: docker build -t gunicorn-and-docker . && docker run -p 8000:8000 -it --rm gunicorn-and-docker

Os registros ficarão assim (pelo menos para mim no macOS Sierra usando 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

Oi,

Recentemente, encontrei o mesmo problema.
No meu caso (ECS + gunicorn 19.7.1 + Django 1.11.5) eu (aparentemente) consegui resolver simplesmente aumentando a quantidade de memória dedicada ao container na definição da tarefa (de 128 para 256mb).
Sem mais erros até agora. Vou relatar aqui se isso acontecer novamente.

Adicionando um pouco ao refrão aqui, mas eu fui capaz de resolver isso apenas mudando para gevent.

Tentei aumentar o tempo limite para 90 e o keepalive para 75 com o trabalhador de sincronização sem sorte.

Além disso, curiosamente, meu ELB neste cenário está apenas fazendo encaminhamento de nível TCP e não HTTP.

Ok, encontrei algumas referências que explicam isso. [1]

Isso poderia ser resolvido com pequenas mudanças no lado do Gunicorn. Se, no trabalhador de sincronização, após aceitar uma nova conexão, chamarmos select() com um tempo limite curto, então poderemos lidar com essas conexões. Pode ser um pouco complicado, especialmente com vários soquetes de escuta. A coisa mais simples seria ter um tempo limite para o primeiro byte. Também não tenho certeza de como isso interagiria com SSL.

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

Se você está passando por isso e não deseja usar gevent / eventlet / asyncio, recomendo mudar para o trabalhador encadeado (forneça a configuração --threads ).

@tilgovi O problema parece existir também com o gevent worker, se você olhar meu exemplo acima.

@jmagnusson seu exemplo (a partir deste comentário: https://github.com/benoitc/gunicorn/issues/1194#issuecomment-331740187) parece estar usando o trabalhador de sincronização.

[2017-09-23 22:31:00 +0000] [1] [INFO] Usando trabalhador: sincronizar

@tilgovi Verdadeiro, mas também experimentei isso com o trabalhador gevent , em produção. Tentarei encontrar algum tempo para reproduzir com gevent.

Posso ser apenas eu (bobo), mas no grupo de segurança EC2 -> regras de entrada, tenho uma regra TCP personalizada para a porta 5000 (gunicorn aqui) para permitir apenas um único IP (meu IP: XX.XX.XX.XX / 32), mudar isso para todos os IPs ajudará.

Eu também encontro o problema.

[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. 

Eu adicionei o log de depuração worker pid {WORKER_PID} notify .

De acordo com o log de depuração,

  1. Somente se o processo de trabalho receber uma solicitação, a notificação não continuará. Portanto, haja ou não as solicitações, o mestre irá encerrar o processo de trabalho após os 30s.
  2. Assim que a primeira solicitação foi fechada, enviei a segunda solicitação agora, mas a segunda solicitação está bloqueada e não há resposta. Quando o tempo limite de 30s atingiu, o processo de trabalho foi eliminado e o novo processo de trabalho responderia à segunda solicitação. Em seguida, o servidor foi interrompido novamente.
  3. Quando o processo de trabalho for interrompido, ele não receberá o sinal do mestre, como SIGTERM . Quando o tempo limite normal chegasse, o mestre o mataria em SIGKILL coercitivamente.
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

AVISO: quando eu uso eventlet como trabalhador, está tudo bem.

Vou encerrar este problema porque acho que está meio desatualizado. Pelo que posso determinar, o comportamento observado é devido ao AWS Classic Load Balancers fazer uma otimização pré-aberta. Essa otimização só é feita por Classic Load Balancers, de acordo com a documentação de funcionamento do load balancing . Mudar para balanceadores de carga de aplicativos deve resolver o problema. Além disso, conforme documentado nesta postagem do blog , é possível solicitar que a AWS desative a otimização pré-aberta ou aumente o tempo limite do trabalhador para Gunicorn.

@tilgovi FWIW Eu vi isso com ALB. Nunca usei balanceadores de carga clássicos.

@tilgovi Eu também observei isso repetidamente em ambientes somente ALB, nunca tendo usado o clássico. Mesmo com ajustes de tempo limite do trabalhador, continuamos a ver isso.

@tilgovi eu me encontrei com isso. Nunca usei AWS.

Alguém tem que ajudar a reproduzir isso, então, e tentar depurá-lo. Não consigo reproduzi-lo com ALB e não consigo ver como reproduzi-lo fora do AWS.

@xgfone você pode querer abrir seu próprio problema, o título deste problema é "docker + AWS"

Alguém experimentou isso com os balanceadores de carga da AWS, mas sem o Docker? Estou um pouco confuso, tenho que admitir :)

Minha impressão era que o problema estava realmente mais relacionado ao Docker - pelo menos eu tive exatamente os mesmos problemas ao executar vários trabalhos de sincronização do gunicorn dentro do Docker em minha máquina local.

Esta configuração funcionou bem sem Docker em máquinas Ubuntu e RHEL, ambos bare metal e virtualizados no Digital Ocean:

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

Dentro do Docker (também RHEL, todo o resto igual), os workers sempre atingiam o tempo limite e continuavam reiniciando permanentemente. Pegando as recomendações deste tópico, mudei para este, que funciona perfeitamente bem:

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

Se você acha que isso não está relacionado a este tópico, estou feliz em removê-lo daqui e colocá-lo em outro lugar ;-)

Atenciosamente, Boris

@tilgovi

Este erro ocorre no arbiter.py, murder_workers . A função murder_workers é chamada quando SIG_QUEUE está vazio (por exemplo, enquanto espera por sinais).

Em seguida, ele verificaria se o tempo limite foi atingido a cada segundo. O tempo restante de vida foi sempre 1 ou 0 segundos porque o trabalhador gevent está em um loop infinito controlado enquanto self.alive invocou self.notify que atualiza um arquivo. As atualizações para o arquivo são como o gunicorn está verificando quando ocorreu o último horário ativo.

Assim, a única maneira de a verificação do tempo de vida na função murder_workers falhar (por exemplo, dizer que está ociosa por muito tempo) é se a propriedade gevent alive foi alterada. Os métodos a seguir controlam isso:

handle_quit
handle_request (se as solicitações máximas foram recebidas, por padrão é 2 ^ 64 bits do número de solicitações ou 2 ^ 32 se o sistema operacional de 32 bits)
changed (invocado do reloader se um arquivo foi alterado)
handle_exit
handle_abort

Esses métodos são invocados a partir de sinais

handle_quit - SIGQUIT, SIGINT
handle_exit - SIGTERM
handle_abort - SIGABRT

Portanto, existem 2 problemas possíveis que vejo:

  1. O método de notificação não é capaz de atualizar o arquivo durante seu ciclo
  2. Um sinal está sendo enviado incorretamente

Acho que a causa mais provável é a 2ª. A principal fonte de sinais está dentro do arquivo do árbitro e acionada por estas exceções:

  • StopIteration
  • KeyboardInterrupt
  • HaltServer
  • Exception (exceção não tratada)

Acho que a exceção StopIteration é provavelmente o culpado disparado no arquivo async.py em req = six.next(parser) . Parece que o próximo método está apenas invocando parser.next ().

Parser.next() levanta uma exceção StopIteration nas 2 condições a seguir:

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

Não tenho certeza do que exatamente pode estar causando isso de forma não intencional, mas de 62 comentários com este problema sendo visto em vários aplicativos e ambientes, acho que vale a pena investigar mais e recomendo reabri-lo ou se não gostamos do título , criar um novo problema global com os trabalhadores atingindo o limite de tempo crítico.

Vou reabrir e tentar testar essas combinações:

  • Docker local
  • Docker AWS com Classic Load Balancer
  • Docker AWS com Balanceador de Carga de Aplicativo

Se alguém quiser criar um repo que possa reproduzir isso, seria útil, mas provavelmente poderei fazê-lo neste fim de semana.

Estou tendo esse problema e não estou usando o AWS.
Minha configuração é NGINX -> contêiner Docker (Gunicorn com gevent workers + Django). Estou usando os tempos limite padrão do Gunicorn.

Alguma dica?

Obrigado.

Olá @davidmir ,
Tive o mesmo problema, mudar o tipo de trabalhador não adiantou. Mudar para um único trabalhador de sincronização com vários threads funcionou para mim:

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

Atenciosamente, Boris

Embora sejam mencionados alguns acima, para esclarecer minha própria depuração desse problema, alguns deles são erros de falta de memória; especialmente se for resolvido alterando a contagem regressiva do trabalhador para 1.

Isso é especialmente problemático no Docker se você tiver algo assim em sua configuração:

workers = multiprocessing.cpu_count() * 2 + 1

Mas estão limitando a memória disponível para o contêiner; o trabalhador síncrono iniciará vários interpretadores python potencialmente pesados. Observe que a contagem da CPU é baseada na contagem geral da CPU da máquina, não no que você provisionou o contêiner do docker para usar; se você estiver executando um contêiner limitado, deve basear a contagem do trabalhador nisso.

Embora varie de aplicativo para aplicativo, minha regra prática é 256 megas por trabalhador em uma configuração enxuta e 512 para ser seguro.

Enfrentou o mesmo problema usando Classic ELB HTTPS => HTTP Gunicorn Sync Workers

Como outros mencionaram, a correção mais fácil era usar o argumento -k gevent vez do trabalhador de sincronização padrão.

Vimos esse mesmo problema surgir novamente para um contêiner Docker totalmente novo (hospedado em ECS atrás do ALB) e encontramos uma solução totalmente diferente (mas em retrospectiva, deveria ter sido óbvia): alocar mais memória para o contêiner em CloudFormation modelo.

Sofremos com esse problema no ano passado e nunca encontramos a causa raiz de uma arma fumegante, mas hoje à noite eu descobri em um novo contêiner e por acaso percebi que o contêiner estava consumindo toda a memória que havíamos alocado. Assim que dobrei a alocação, os contêineres pararam de lançar este erro (mesmo antes de eu alocar mais do que acabaria por consumir):
https://github.com/hackoregon/civic-devops/issues/157

Enfrentando um problema semelhante aqui. o código é tão simples quanto

while true:
      sleep(10)

pode levar o trabalhador à morte (sem este código, nossa implantação é normal)
é muito intrigante, b / c sleep deve enviar um batimento cardíaco.

também já mudou para gevent, não ajudou. Será que alguém tem algum pensamento?

saída de amostra:
[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

Desculpe por turvar as águas aqui, mas só queria compartilhar minha experiência, minha pilha é HTTP ELB > Nginx > gunicorn/gevent on EC2 , processos executados usando circusd

O problema que descobri foi que, após instrumentar meu aplicativo django com elastic-apm, minhas verificações de integridade de HTTP começarão a falhar quase imediatamente e o gunicorn deixaria de responder após alguns segundos.

Eu tentei alguns benchmarks locais de wrk contra minha verificação de saúde, a sincronização estava obtendo cerca de 300rps para 1-5 workers, mas o gevent recebia 1rps. Desligar o apm aumentou o gevent até cerca de 50 rps e um aumento desprezível para a sincronização.

Não notei nenhum uso estranho de memória no valgrind, normalmente cerca de 4 MB para gunicorn e 40 MB por trabalhador

De qualquer forma, atualizar gunicorn 19.6.0 > 19.9.0 e gevent 1.2.2 > 1.3.6 está me dando uma excelente verificação de integridade do ELB novamente e ~ 300rps localmente. Deliberadamente, não estive atualizando o gunicorn / gevent até que algum registro do APM estivesse em vigor, parece que fazer isso gerou algum acaso. A atualização do gevent deu o maior impulso, compreensivelmente, mas a atualização do gunicorn pareceu adicionar outros 10% ou mais.

Ainda não olhou para os changelogs com muitos detalhes, talvez os mantenedores possam lançar luz sobre a causa mais provável?

De qualquer forma, atualizar gunicorn 19.6.0> 19.9.0 e gevent 1.2.2> 1.3.6 está me dando uma excelente verificação de integridade de ELB novamente e ~ 300rps localmente ... Atualizar gevent deu o maior impulso

Uau, isso é muito legal!

edição de encerramento. nenhuma atividade desde há algum tempo.

FWIW, ainda estou tendo esse problema @benoitc : - \

Django 2.1.5
gunicorn 19.8.1
gevent 1.2.2
AKS 1.15.7 com 5 nós (padrão B2's - 2 vcores e 2 GB de memória)
3 pods / contêineres docker, cada um dos quais com:

    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"

O mesmo problema aqui com EKS, Nginx e um NLB.

@salmicrosoft @sinkr OK, mas abra um novo problema e forneça todos os logs que você possui que podem nos ajudar a descobrir o que aconteceu. Além disso, o que seu aplicativo faz? Você tem algum pedido longo?

Tive o mesmo problema no ECS Fargate, mas estava relacionado a configurações incorretas de keepalive / timeout em Docker / gunicorn.conf.py, era
keepalive (não definido)
tempo limite = 2

Antes de consertar, funciona bem com um contêiner rodando localmente, mas falhou no ECS Fargate, agora funciona corretamente em ambos os ambientes.

Esta página foi útil?
0 / 5 - 0 avaliações