Gunicorn: "Booting worker" está em loop infinito, apesar de nenhum sinal de saída

Criado em 11 dez. 2017  ·  65Comentários  ·  Fonte: benoitc/gunicorn

Estou tentando configurar o gunicorn no Docker. Funciona bem localmente e a imagem de produção é exatamente igual à imagem local, mas estou percebendo este comportamento estranho no mecanismo de produção do Docker:

ml-server_1     | [2017-12-11 13:18:50 +0000] [1] [INFO] Starting gunicorn 19.7.1
ml-server_1     | [2017-12-11 13:18:50 +0000] [1] [DEBUG] Arbiter booted
ml-server_1     | [2017-12-11 13:18:50 +0000] [1] [INFO] Listening at: http://0.0.0.0:80 (1)
ml-server_1     | [2017-12-11 13:18:50 +0000] [1] [INFO] Using worker: sync
ml-server_1     | [2017-12-11 13:18:50 +0000] [8] [INFO] Booting worker with pid: 8
ml-server_1     | [2017-12-11 13:18:50 +0000] [1] [DEBUG] 1 workers
ml-server_1     | Using TensorFlow backend.
ml-server_1     | [2017-12-11 13:18:54 +0000] [11] [INFO] Booting worker with pid: 11
ml-server_1     | Using TensorFlow backend.
ml-server_1     | [2017-12-11 13:18:58 +0000] [14] [INFO] Booting worker with pid: 14
ml-server_1     | Using TensorFlow backend.
ml-server_1     | [2017-12-11 13:19:02 +0000] [17] [INFO] Booting worker with pid: 17
ml-server_1     | Using TensorFlow backend.

Parece que o gunicorn está inicializando os workers a cada 4-5 segundos, apesar de nenhuma mensagem de erro aparente ou sinais de saída. Este comportamento continua indefinidamente até que seja encerrado.

É possível que um trabalhador possa sair sem registrar nada em stderr / stdout ou para o árbitro gerar trabalhadores infinitamente?

Como eles são a mesma imagem do docker, eles estão executando exatamente o mesmo código, exatamente na mesma arquitetura, então estou realmente confuso o que isso poderia ser (bug?). Qualquer ajuda muito apreciada!

Improvement help wanted

Comentários muito úteis

Apenas para uma atualização, o problema para mim era na verdade um erro de memória e foi corrigido quando o problema de memória foi corrigido.

Todos 65 comentários

ssh -ing no contêiner do Docker me levou a encontrar este erro:

Illegal instruction (core dumped)

Talvez o gunicorn deva revelar erros como esse em vez de engoli-los, ou tratá-los de maneira diferente? Não tenho certeza, só pensei em levantar isso, pois poderia ajudar outra pessoa!

Obrigado por relatar o problema!

Se você conseguir descobrir onde isso acontece, será muito útil.

Talvez possamos adicionar o registro quando os trabalhadores saem. Normalmente, o próprio trabalhador registra, mas se for morto muito abruptamente, não o fará.

Sem problemas!

Parece haver um problema com o Spacy que acabei de adicionar a este tópico: https://github.com/explosion/spaCy/issues/1589

De qualquer forma, está causando um SIGILL pois strace confirma:

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

Suponho que seria bom se o gunicorn pudesse identificar isso e registrar um erro em vez de reiniciar fantasmagoricamente o trabalhador, mas tbh eu sei muito pouco sobre como funcionam os códigos de saída!

Alguns códigos de saída definitivamente têm significados especiais e provavelmente poderíamos registrá-los.
http://tldp.org/LDP/abs/html/exitcodes.html

Soa bem! Além disso, se o código de saída não for um código de saída reservado (como neste caso), seria legal se isso pudesse ser registrado (sem uma explicação), então é aparente que o trabalhador está realmente encerrando 🙂

Eu tenho um tipo de problema semelhante, o gunicorn está inicializando um novo trabalhador sempre que faço uma solicitação de http. Não recebo nenhuma resposta de volta, apenas reinicializa o novo trabalhador sempre. Log do Strace de duas solicitações http:

select(4, [3], [], [], {1, 0})          = 0 (Timeout)
fstat(6, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
fstat(7, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
fstat(9, {st_mode=S_IFREG, st_size=0, ...}) = 0
fstat(8, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
select(4, [3], [], [], {1, 0})          = ? ERESTARTNOHAND (To be restarted if no handler)
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_KILLED, si_pid=510, si_uid=0, si_status=SIGSEGV, si_utime=160, si_stime=32} ---
getpid()                                = 495
rt_sigreturn({mask=[]})                 = -1 EINTR (Interrupted system call)
wait4(-1, [{WIFSIGNALED(s) && WTERMSIG(s) == SIGSEGV && WCOREDUMP(s)}], WNOHANG, NULL) = 510
lseek(8, 0, SEEK_CUR)                   = 0
close(8)                                = 0
wait4(-1, 0x7ffd455ad844, WNOHANG, NULL) = 0
write(4, ".", 1)                        = 1
select(4, [3], [], [], {0, 840340})     = 1 (in [3], left {0, 840338})
read(3, ".", 1)                         = 1
read(3, 0x7f2682025fa0, 1)              = -1 EAGAIN (Resource temporarily unavailable)
fstat(6, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
fstat(7, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
fstat(9, {st_mode=S_IFREG, st_size=0, ...}) = 0
umask(0)                                = 022
getpid()                                = 495
open("/tmp/wgunicorn-q4aa72u7", O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW|O_CLOEXEC, 0600) = 8
fcntl(8, F_SETFD, FD_CLOEXEC)           = 0
chown("/tmp/wgunicorn-q4aa72u7", 0, 0)  = 0
umask(022)                              = 0
unlink("/tmp/wgunicorn-q4aa72u7")       = 0
fstat(8, {st_mode=S_IFREG|0600, st_size=0, ...}) = 0
ioctl(8, TIOCGWINSZ, 0x7ffd455b8e50)    = -1 ENOTTY (Not a tty)
lseek(8, 0, SEEK_CUR)                   = 0
lseek(8, 0, SEEK_CUR)                   = 0
rt_sigprocmask(SIG_BLOCK, ~[], [], 8)   = 0
fork()                                  = 558
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
select(0, NULL, NULL, NULL, {0, 37381}[2017-12-28 17:50:23 +0000] [558] [INFO] Booting worker with pid: 558
) = 0 (Timeout)
select(4, [3], [], [], {1, 0}loading test-eu-ovh settings
)          = 0 (Timeout)
fstat(6, {st_mode=S_IFREG, st_size=0, ...}) = 0
fstat(7, {st_mode=S_IFREG, st_size=0, ...}) = 0
fstat(9, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
fstat(8, {st_mode=S_IFREG|0600, st_size=0, ...}) = 0
select(4, [3], [], [], {1, 0}
)          = 0 (Timeout)
fstat(6, {st_mode=S_IFREG, st_size=0, ...}) = 0
fstat(7, {st_mode=S_IFREG, st_size=0, ...}) = 0
fstat(9, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
fstat(8, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
select(4, [3], [], [], {1, 0})          = 0 (Timeout)
fstat(6, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
fstat(7, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
fstat(9, {st_mode=S_IFREG, st_size=0, ...}) = 0
fstat(8, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
select(4, [3], [], [], {1, 0})          = 0 (Timeout)
fstat(6, {st_mode=S_IFREG, st_size=0, ...}) = 0
fstat(7, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
fstat(9, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
fstat(8, {st_mode=S_IFREG, st_size=0, ...}) = 0
select(4, [3], [], [], {1, 0})          = 0 (Timeout)
fstat(6, {st_mode=S_IFREG, st_size=0, ...}) = 0
fstat(7, {st_mode=S_IFREG, st_size=0, ...}) = 0
fstat(9, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
fstat(8, {st_mode=S_IFREG, st_size=0, ...}) = 0
select(4, [3], [], [], {1, 0})          = 0 (Timeout)
fstat(6, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
fstat(7, {st_mode=S_IFREG, st_size=0, ...}) = 0
fstat(9, {st_mode=S_IFREG, st_size=0, ...}) = 0
fstat(8, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
select(4, [3], [], [], {1, 0})          = 0 (Timeout)
fstat(6, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
fstat(7, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
fstat(9, {st_mode=S_IFREG, st_size=0, ...}) = 0
fstat(8, {st_mode=S_IFREG, st_size=0, ...}) = 0
select(4, [3], [], [], {1, 0})          = ? ERESTARTNOHAND (To be restarted if no handler)
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_KILLED, si_pid=499, si_uid=0, si_status=SIGSEGV, si_utime=160, si_stime=31} ---
getpid()                                = 495
rt_sigreturn({mask=[]})                 = -1 EINTR (Interrupted system call)
wait4(-1, [{WIFSIGNALED(s) && WTERMSIG(s) == SIGSEGV && WCOREDUMP(s)}], WNOHANG, NULL) = 499
lseek(7, 0, SEEK_CUR)                   = 0
close(7)                                = 0
wait4(-1, 0x7ffd455ad844, WNOHANG, NULL) = 0
write(4, ".", 1)                        = 1
select(4, [3], [], [], {0, 450691})     = 1 (in [3], left {0, 450689})
read(3, ".", 1)                         = 1
read(3, 0x7f2682067de8, 1)              = -1 EAGAIN (Resource temporarily unavailable)
fstat(6, {st_mode=S_IFREG, st_size=0, ...}) = 0
fstat(9, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
fstat(8, {st_mode=S_IFREG, st_size=0, ...}) = 0
umask(0)                                = 022
getpid()                                = 495
open("/tmp/wgunicorn-5x9a40ca", O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW|O_CLOEXEC, 0600) = 7
fcntl(7, F_SETFD, FD_CLOEXEC)           = 0
chown("/tmp/wgunicorn-5x9a40ca", 0, 0)  = 0
umask(022)                              = 0
unlink("/tmp/wgunicorn-5x9a40ca")       = 0
fstat(7, {st_mode=S_IFREG|0600, st_size=0, ...}) = 0
ioctl(7, TIOCGWINSZ, 0x7ffd455b8e50)    = -1 ENOTTY (Not a tty)
lseek(7, 0, SEEK_CUR)                   = 0
lseek(7, 0, SEEK_CUR)                   = 0
rt_sigprocmask(SIG_BLOCK, ~[], [], 8)   = 0
fork()                                  = 579
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
select(0, NULL, NULL, NULL, {0, 8144}[2017-12-28 17:50:30 +0000] [579] [INFO] Booting worker with pid: 579
)  = 0 (Timeout)
select(4, [3], [], [], {1, 0})          = 0 (Timeout)
fstat(6, {st_mode=S_IFREG, st_size=0, ...}) = 0
fstat(7, {st_mode=S_IFREG|0600, st_size=0, ...}) = 0
fstat(9, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
fstat(8, {st_mode=S_IFREG|01, st_size=0, ...}) = 0

Estou enfrentando o mesmo problema, gunicorn está inicializando repetidamente em segundos para o tipo de trabalhador sync . Definir o tempo limite do trabalhador para 900 não está ajudando.

Em minha carga antes da ação, estou baixando dados do AWS S3. Demora cerca de 1 minuto e 10 segundos para baixar os vários arquivos.

@ sara-02 qual é a sua linha de comando para iniciar o gunicorn?

@benoitc gunicorn --pythonpath /src -b 0.0.0.0:$SERVICE_PORT --workers=1 -k sync -t $SERVICE_TIMEOUT flask_endpoint:app
Apresentar aqui

@ sara-02 Obrigado.

Os trabalhadores antigos estão realmente saindo ou são mantidos online e novos trabalhadores são gerados? O que o log de depuração também mostra?

Os logs são misturados com os logs do botocore, mas é algo assim

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

mas o trabalhador é morto? o que retorna o comando ps ax|grep gunicorn ?

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

Uma pergunta, porém, por que vemos 2 gunicorn processos, quando o limite do trabalhador é definido como 1? É um mestre e um trabalhador?

Há 1 processo de árbitro (mestre) e N processos de trabalho, você :)

Então você executa o comando toda vez que um trabalhador inicializa, certo? Se assim for, parece que o trabalhador mais velho é morto, um novo é gerado. Eu investigarei.

@ sara-02 uma última coisa, isso também está acontecendo no docker?

@benoitc em docker-compose está funcionando como esperado, mas quando estou colocando o mesmo código em Openshift , vejo este erro. Aumentar o requisito de memória foi corrigido, mas quando executo o aplicativo por meio de docker-compose ele está usando menos de limited memória.

Apenas para uma atualização, o problema para mim era na verdade um erro de memória e foi corrigido quando o problema de memória foi corrigido.

@benoitc
Estou enfrentando o mesmo problema ao tentar gerar 5 gunicorn worker no docker.
@ sara-02
Como você identificou a causa de um erro de memória?

image

@ gulshan-gaurav 2 coisas me ajudaram:
Aumentei a memória atribuída ao meu Pod e parei de travar. Em segundo lugar, verificamos nossos logs do Openshift Zabbix.

@ sara-02
Mesmo no meu pod de teste, os arquivos + modelos que estou carregando na memória chegam a 50 MB, então 2 GB de memória devem ser suficientes para 5 trabalhadores.

@ gulshan-gaurav que problema você está enfrentando? Ter 5 processos parece bom ...

Eu tive o mesmo problema. Não localizei o problema exato, mas foi resolvido assim que atualizei do python 3.5 para o 3.6.

Estou enfrentando o mesmo problema em um contêiner do Docker. O Gunicorn continua enviando um bot para um novo trabalhador toda vez que eu chamo um endpoint que causa a falha, mas não a exceção ou o erro é gerado nos arquivos de log do Gunicorn. As coisas que escolhi imprimir são registradas e, de repente, o arquivo de log apenas diz "Booting worker with pid ..."

Uma etapa que ajudou foi adicionar a variável env PYTHONUNBUFFERED. Antes disso, mesmo as declarações de impressão desapareceriam e não seriam salvas nos registros de Gunicorn.

2 outros endpoints do aplicativo funcionam corretamente.

Eu executo o Gunicorn com: gunicorn run: app -b localhost: 5000 --enable-stdio-inheritance --error-logfile /var/log/gunicorn/error.log --access-logfile / var / log / gunicorn / access. log --capture-output --log-level debug

Já executando o Python 3.6 e verifiquei com o top se a memória não parece ser um problema.

EDIT: Parece que foi um problema do Python e não uma falha do Gunicorn. Algumas discrepâncias de versão faziam com que o Python simplesmente morresse sem deixar vestígios durante a execução de uma determinada operação.

Estou enfrentando um problema semelhante em que o nó de trabalho continua surgindo com
Booting worker with pid: 17636 . não sei se ele está matando o nó de trabalho anterior ou o nó de trabalho anterior ainda existe. Mas o número de trabalhadores mencionados nos argumentos da linha de comando do gunicorn é apenas 3 - -workers=3 . Também estou usando o python versão 3.7

Tive uma incompatibilidade de dependência de scikit-learn, mas mesmo depois de resolver isso, ainda estou recebendo os mesmos trabalhadores infinitos. que tipo de discrepâncias de versão de python devo procurar e como identificá-las?

Estou enfrentando o mesmo problema no OpenShift.

image

Como você pode ver na imagem, estou usando 6 workers (estava tentando com 3).
Aumentei a memória do pod e não funcionou.

BuildConfig:

image

Qualquer ideia?

Obrigado

você está executando isso em aws atrás do cotovelo? Resolvi esse problema colocando nginx ingress entre elb e gunicorn

Tem o mesmo problema.

flask_1  | [2019-02-23 09:08:17 +0000] [1] [INFO] Starting gunicorn 19.9.0
flask_1  | [2019-02-23 09:08:17 +0000] [1] [INFO] Listening at: http://0.0.0.0:5000 (1)
flask_1  | [2019-02-23 09:08:17 +0000] [1] [INFO] Using worker: sync
flask_1  | [2019-02-23 09:08:17 +0000] [8] [INFO] Booting worker with pid: 8
flask_1  | [2019-02-23 09:08:19 +0000] [12] [INFO] Booting worker with pid: 12
flask_1  | [2019-02-23 09:08:19 +0000] [16] [INFO] Booting worker with pid: 16
flask_1  | [2019-02-23 09:08:20 +0000] [20] [INFO] Booting worker with pid: 20
flask_1  | [2019-02-23 09:08:21 +0000] [24] [INFO] Booting worker with pid: 24
flask_1  | [2019-02-23 09:08:22 +0000] [28] [INFO] Booting worker with pid: 28
flask_1  | [2019-02-23 09:08:23 +0000] [32] [INFO] Booting worker with pid: 32
flask_1  | [2019-02-23 09:08:25 +0000] [36] [INFO] Booting worker with pid: 36
flask_1  | [2019-02-23 09:08:26 +0000] [40] [INFO] Booting worker with pid: 40
flask_1  | [2019-02-23 09:08:27 +0000] [44] [INFO] Booting worker with pid: 44
flask_1  | [2019-02-23 09:08:29 +0000] [48] [INFO] Booting worker with pid: 48
flask_1  | [2019-02-23 09:08:30 +0000] [52] [INFO] Booting worker with pid: 52
flask_1  | [2019-02-23 09:08:31 +0000] [56] [INFO] Booting worker with pid: 56
flask_1  | [2019-02-23 09:08:33 +0000] [60] [INFO] Booting worker with pid: 60
flask_1  | [2019-02-23 09:08:34 +0000] [64] [INFO] Booting worker with pid: 64
flask_1  | [2019-02-23 09:08:35 +0000] [68] [INFO] Booting worker with pid: 68
flask_1  | [2019-02-23 09:08:36 +0000] [72] [INFO] Booting worker with pid: 72
flask_1  | [2019-02-23 09:08:37 +0000] [76] [INFO] Booting worker with pid: 76
flask_1  | [2019-02-23 09:08:38 +0000] [80] [INFO] Booting worker with pid: 80
flask_1  | [2019-02-23 09:08:40 +0000] [84] [INFO] Booting worker with pid: 84
flask_1  | [2019-02-23 09:08:41 +0000] [88] [INFO] Booting worker with pid: 88
flask_1  | [2019-02-23 09:08:42 +0000] [92] [INFO] Booting worker with pid: 92
flask_1  | [2019-02-23 09:08:44 +0000] [96] [INFO] Booting worker with pid: 96
flask_1  | [2019-02-23 09:08:45 +0000] [100] [INFO] Booting worker with pid: 100
flask_1  | [2019-02-23 09:08:45 +0000] [104] [INFO] Booting worker with pid: 104
flask_1  | [2019-02-23 09:08:46 +0000] [108] [INFO] Booting worker with pid: 108
flask_1  | [2019-02-23 09:08:47 +0000] [112] [INFO] Booting worker with pid: 112
flask_1  | [2019-02-23 09:08:48 +0000] [116] [INFO] Booting worker with pid: 116
flask_1  | [2019-02-23 09:08:49 +0000] [120] [INFO] Booting worker with pid: 120
flask_1  | [2019-02-23 09:08:50 +0000] [124] [INFO] Booting worker with pid: 124
flask_1  | [2019-02-23 09:08:52 +0000] [128] [INFO] Booting worker with pid: 128

Aqui está docker-compose.yml :

version: '3'
services:
  flask:
    build: .
    command: gunicorn -b 0.0.0.0:5000 hello:app --reload
    environment:
      - FLASK_APP=hello.py
      - FLASK_DEBUG=1
      - PYTHONUNBUFFERED=True
    ports:
      - "5000:5000"
    volumes:
      - ./:/root

que imagem docker ele usa?

@benoitc

[ec2-user@ip-172-31-85-181 web-services-course]$ docker --version
Docker version 18.06.1-ce, build e68fc7a215d7133c34aa18e3b72b4a21fd0c6136
[ec2-user@ip-172-31-85-181 web-services-course]$ docker-compose --version
docker-compose version 1.23.2, build 1110ad01

Aqui estão os links para:

descobri que pode ser causado por falta de memória. o aplicativo precisa de mais memória do que está disponível.
mas é apenas suposição

Apenas como informação: observei exatamente esse comportamento quando tenho um gunicorn conf para 3 workers, mas implantei o código em uma máquina virtual com uma CPU de núcleo único. Então, mudei o ambiente para usar 2 núcleos e, obviamente, o problema desapareceu

Por que 'Trabalhador está saindo' apenas no nível INFO - por que um trabalhador sairia, exceto como resultado de um erro? Levei muito tempo para descobrir que meus threads de trabalho estavam sendo encerrados pelo assassino OOM do sistema, sem nada nos logs, exceto, conforme relatado por alguns outros acima, 'Inicializando o trabalhador com pid' de tempos em tempos.

@HughWarrington porque a saída de um trabalhador não é necessariamente um erro. Os trabalhadores podem ser demitidos por sinais ou por opções como --max-requests .

@HughWarrington , provavelmente poderíamos adicionar o registro no árbitro para quando um trabalhador sair com um código de saída anormal.

Você pode abrir um tíquete para isso ou contribuir com um PR que adiciona este código ao método reap_workers .

Eu tive o mesmo problema e a solução foi aumentar o tamanho da memória do pod.

Teve o mesmo problema ao executar o Gunicorn no Docker com um modelo spaCy grande, ele reiniciou os workers sem nenhuma mensagem de erro. A solução é aumentar a memória do contêiner Docker.

Acabei de encontrar esse problema hoje no último (19.9.0) gunicorn com gevent (1.4.0) workers em execução no Kubernetes. O aplicativo é um aplicativo Falcon e a imagem Docker é a imagem oficial do Python com a tag 3.7.3 .

[2019-07-05 00:07:42 +0000] [8] [INFO] Starting gunicorn 19.9.0
[2019-07-05 00:07:42 +0000] [8] [INFO] Listening at: http://0.0.0.0:5000 (8)
[2019-07-05 00:07:42 +0000] [8] [INFO] Using worker: gevent
[2019-07-05 00:07:43 +0000] [35] [INFO] Booting worker with pid: 35
[2019-07-05 00:07:43 +0000] [36] [INFO] Booting worker with pid: 36
[2019-07-05 00:07:43 +0000] [37] [INFO] Booting worker with pid: 37
[2019-07-05 00:07:43 +0000] [38] [INFO] Booting worker with pid: 38
[2019-07-05 00:07:43 +0000] [41] [INFO] Booting worker with pid: 41
[2019-07-05 00:07:43 +0000] [43] [INFO] Booting worker with pid: 43
[2019-07-05 00:07:43 +0000] [45] [INFO] Booting worker with pid: 45
[2019-07-05 00:07:43 +0000] [49] [INFO] Booting worker with pid: 49
[2019-07-05 00:07:43 +0000] [47] [INFO] Booting worker with pid: 47
[2019-07-05 00:07:49 +0000] [53] [INFO] Booting worker with pid: 53
[2019-07-05 00:07:50 +0000] [54] [INFO] Booting worker with pid: 54
[2019-07-05 00:07:53 +0000] [57] [INFO] Booting worker with pid: 57
[...]

O pod tinha as seguintes configurações de recursos:

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

Dobrar tudo resolveu o problema.

Uma coisa interessante que notamos foi que ao olhar para dmesg na máquina host, podemos ver que está segfault -ing em libcrypto ao acessar o servidor usando SSL

A memória parece não ser um problema para mim porque não estou carregando nenhum modelo grande na memória. Os funcionários continuam travando e não consigo ver nenhuma mensagem de erro. Existe uma correção para isso?

image

mesmo problema para mim, alguma ideia para consertar? python 3.6.3 com gunicorn 19.9.0

@MrKiven o que faz seu aplicativo? você está usando coisas como pedido?

alguém pode fornecer uma maneira de reproduzir o problema?

É um gerenciador de vários componentes que são executados em um pipeline. Alguns deles podem iniciar solicitações HTTP para outros componentes na mesma máquina ou em máquinas remotas. Alguns dos módulos do pipeline podem ser executados em paralelo, mas são executados usando um ThreadPoolExecutor. Eles não usam nenhum objeto compartilhado, mas apenas geram estruturas de dados que são posteriormente agregadas em um único resultante.

Infelizmente, não tenho certeza se posso montar um exemplo mínimo sem expor o sistema que temos.

O request faz muitas coisas inseguras com threads que às vezes bifurcam um novo processo. Aconselho a usar outro cliente. você pode colar pelo menos as linhas que está usando para fazer uma solicitação? Você está usando o recurso de tempo limite?

Um deles pode ser:

try:
     resp = requests.post(self._endpoint, json=request_data)

     if resp.status_code != 200:
          logger.critical("[Error]: status code is {}".format(resp.status_code))
          return None

     response = resp.json()
     return {"intent": response["intent"], "intent_ranking": response["intent_ranking"]}
except ConnectionError as exc:
     logger.critical("[Exception] {}".format(str(exc)))
     return None

Obrigado. Vou tentar criar um simples a partir dele.

De qualquer forma, seria legal se alguém pudesse nos enviar um pr que reproduzisse o comportamento como um exemplo ou um teste de unidade para ter certeza de que estamos corrigindo a coisa certa.

Não tenho certeza se isso pode ajudar alguém, mas tive o mesmo problema ao executar um webapp de frasco dockerizado e resolvi atualizando a imagem base do meu dockerfile para python:3.6.9-alpine

Dmesg no host mostrou um segfault em lilibpython3.6m.so.1.0:

[626278.653010] gunicorn[19965]: segfault at 70 ip 00007f6423e7faee sp 00007ffc4e9a2a38 error 4 in libpython3.6m.so.1.0[7f6423d8a000+194000]

Minha imagem docker foi baseada em python:3.6-alpine e fazendo um apk update que estava atualizando o python para 3.6.8.

Como disse, mudar a imagem de base para python:3.6.9-alpine resolveu para mim

Enfrentei o mesmo desafio executando um Flask + Docker + Kubernetes. Aumentar os limites de CPU e memória resolveu para mim.

A mesma coisa aconteceu conosco. O aumento dos limites de recursos corrigiu o problema.

Isso de repente aconteceu comigo no macOS Catalina (não em contêineres).

O que me ajudou foi:

  1. Instalando o openssl:
brew install openssl
  1. Executando e adicionando isso ao meu ~/.zshrc :
export DYLD_LIBRARY_PATH=/usr/local/opt/openssl/lib:$DYLD_LIBRARY_PATH

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

Estou tendo um desafio semelhante e ficaria grato se alguém pudesse me ajudar.
Isso é o que eu tinha;

" root @ ubuntu-s-1vcpu-1gb-nyc1-01 : ~ # sudo systemctl status gunicorn.service ● gunicorn.service - daemon gunicorn Carregado: carregado (/etc/systemd/system/gunicorn.service; desativado; predefinição do fornecedor: ativado) Ativo: ativo (em execução) desde Seg 2020-02-24 07:48:04 UTC; 44min atrás PID principal: 4846 (gunicorn) Tarefas: 4 (limite: 1151) CGrupo: /system.slice/gunicorn.service ├ ─4846 / home / bright / djangoprojectdir / djangoprojectenv / bin / python / home / bright / djangoprojectdir / djangoprojectenv / bin / gunicorn - ├─4866 / home / bright / djangoprojectdir / djangoprojectdirjang / djangoprojectdir / djangoprojectenv / bin / gunicorn - ├─4866 / home / bright / djangoprojectdir / djangoprojectdirjang / djangoprojectdir / djangoprojectenv / bin / gunicorn - ├─4866 / home / bright / djangoprojectdir / djangoprojectenv / bin / python / bright / bin / gunicorn - ├─4868 / home / bright / djangoprojectdir / djangoprojectenv / bin / python / home / bright / djangoprojectdir / djangoprojectenv / bin / gunicorn - └─4869 / home / bright / djangoprojectdir / djangoprojectdir / djangoprojectenv / home / bin / bin python / / bright / djangoprojectdir / djangoprojectenv / bin / gunicorn - 24 de fevereiro 07:48:04 ubuntu-s-1vcpu-1gb-nyc1-01 systemd [1]: daemon gunicorn interrompido. 24 de fevereiro 07:48:04 ubuntu-s-1vcpu -1gb-nyc1-01 systemd [1 ]: Daemon gunicorn iniciado. 24 de fevereiro 07:48:05 ubuntu-s-1vcpu-1gb-nyc1-01 gunicorn [4846]: [2020-02-24 07:48:05 +0000] [4846] [INFO] Iniciando gunicorn 20.0.4 24 de fevereiro 07:48:05 ubuntu-s-1vcpu-1gb-nyc1-01 gunicorn [4846]: [2020-02-24 07:48:05 +0000] [4846] [INFO] Ouvindo em: unix: / run / gunicorn .soc 24 de fevereiro 07:48:05 ubuntu-s-1vcpu-1gb-nyc1-01 gunicorn [4846]: [2020-02-24 07:48:05 +0000] [4846] [INFO] Usando trabalhador: sincronizar fevereiro 24 07:48:05 ubuntu-s-1vcpu-1gb-nyc1-01 gunicorn [4846]: [2020-02-24 07:48:05 +0000] [4866] [INFO] Booting worker com pid: 4866 24 de fevereiro 07:48:05 ubuntu-s-1vcpu-1gb-nyc1-01 gunicorn [4846]: [2020-02-24 07:48:05 +0000] [4868] [INFO] Booting worker com pid: 4868 Fev 24 07 : 48: 05 ubuntu-s-1vcpu-1gb-nyc1-01 gunicorn [4846]: [2020-02-24 07:48:05 +0000] [4869] [INFO] Operador de inicialização com pid: 4869 24 de fevereiro 08: 03:41 ubuntu-s-1vcpu-1gb-nyc1-01 gunicorn [4846]: - - [24 / Fev / 2020: 08: 03: 41 +0000] "GET / HTTP / 1.0" 400 26 "-" "Mozilla /5.0 (Wi lines 1-20 / 20 (END) "Alguém pode me ajudar a consertar isso?

@BrightNana você pode tentar dar um dmesg e ver se você tem algum erro de gunicorn?
dmesg | grep gunicorn pode ajudar a filtrar os outros erros

Olá,
Eu tenho o mesmo bug no debian 9 quando desejo fornecer o gunicorn como um serviço systemd. Se eu iniciá-lo a partir da CLI, o gunicorn será executado sem erros.

Extrair de dmesg | grep gunicorn :

Trecho de journalctl :
Mär 12 07:01:06 build-server gunicorn[828]: [2020-03-12 07:01:06 +0100] [1054] [INFO] Booting worker with pid: 1054 Mär 12 07:01:06 build-server gunicorn[828]: [2020-03-12 07:01:06 +0100] [1057] [INFO] Booting worker with pid: 1057 Mär 12 07:01:06 build-server gunicorn[828]: [2020-03-12 07:01:06 +0100] [1060] [INFO] Booting worker with pid: 1060 Mär 12 07:01:07 build-server gunicorn[828]: [2020-03-12 07:01:07 +0100] [1064] [INFO] Booting worker with pid: 1064 Mär 12 07:01:07 build-server gunicorn[828]: [2020-03-12 07:01:07 +0100] [1067] [INFO] Booting worker with pid: 1067 Mär 12 07:01:07 build-server gunicorn[828]: [2020-03-12 07:01:07 +0100] [1070] [INFO] Booting worker with pid: 1070 Mär 12 07:01:07 build-server gunicorn[828]: [2020-03-12 07:01:07 +0100] [1073] [INFO] Booting worker with pid: 1073 Mär 12 07:01:07 build-server gunicorn[828]: [2020-03-12 07:01:07 +0100] [1076] [INFO] Booting worker with pid: 1076 Mär 12 07:01:08 build-server gunicorn[828]: [2020-03-12 07:01:08 +0100] [1079] [INFO] Booting worker with pid: 1079 Mär 12 07:01:08 build-server gunicorn[828]: [2020-03-12 07:01:08 +0100] [1082] [INFO] Booting worker with pid: 1082 Mär 12 07:01:08 build-server gunicorn[828]: [2020-03-12 07:01:08 +0100] [1085] [INFO] Booting worker with pid: 1085 Mär 12 07:01:08 build-server gunicorn[828]: [2020-03-12 07:01:08 +0100] [1088] [INFO] Booting worker with pid: 1088 Mär 12 07:01:08 build-server gunicorn[828]: [2020-03-12 07:01:08 +0100] [1091] [INFO] Booting worker with pid: 1091 Mär 12 07:01:09 build-server gunicorn[828]: [2020-03-12 07:01:09 +0100] [1094] [INFO] Booting worker with pid: 1094
Extrair de systemctl status :
● api.service - API Server for BuildingChallenge served with Gunicorn Loaded: loaded (/etc/systemd/system/api.service; disabled; vendor preset: enabled) Active: active (running) since Thu 2020-03-12 08:26:01 CET; 22min ago Main PID: 8150 (gunicorn) Tasks: 3 (limit: 4915) Memory: 37.7M (high: 100.0M max: 500.0M) CGroup: /system.slice/api.service ├─ 8150 /opt/api/venv/bin/python /opt/api/venv/bin/gunicorn --bind unix:api.sock wsgi:app ├─28936 /opt/api/venv/bin/python /opt/api/venv/bin/gunicorn --bind unix:api.sock wsgi:app └─28938 /usr/bin/python3 -Es /usr/bin/lsb_release -a Mär 12 08:48:01 build-server gunicorn[8150]: [2020-03-12 08:48:01 +0100] [28909] [INFO] Booting worker with pid: 28909 Mär 12 08:48:01 build-server gunicorn[8150]: [2020-03-12 08:48:01 +0100] [28912] [INFO] Booting worker with pid: 28912 Mär 12 08:48:01 build-server gunicorn[8150]: [2020-03-12 08:48:01 +0100] [28915] [INFO] Booting worker with pid: 28915 Mär 12 08:48:01 build-server gunicorn[8150]: [2020-03-12 08:48:01 +0100] [28918] [INFO] Booting worker with pid: 28918 Mär 12 08:48:01 build-server gunicorn[8150]: [2020-03-12 08:48:01 +0100] [28921] [INFO] Booting worker with pid: 28921 Mär 12 08:48:01 build-server gunicorn[8150]: [2020-03-12 08:48:01 +0100] [28924] [INFO] Booting worker with pid: 28924 Mär 12 08:48:02 build-server gunicorn[8150]: [2020-03-12 08:48:02 +0100] [28927] [INFO] Booting worker with pid: 28927 Mär 12 08:48:02 build-server gunicorn[8150]: [2020-03-12 08:48:02 +0100] [28930] [INFO] Booting worker with pid: 28930 Mär 12 08:48:02 build-server gunicorn[8150]: [2020-03-12 08:48:02 +0100] [28933] [INFO] Booting worker with pid: 28933 Mär 12 08:48:02 build-server gunicorn[8150]: [2020-03-12 08:48:02 +0100] [28936] [INFO] Booting worker with pid: 28936

Obrigado pela ajuda.

Eu coloquei um PR que pode ajudar a depurar esse tipo de situação. Alguém pode dar uma olhada?
https://github.com/benoitc/gunicorn/pull/2315

Tive o mesmo problema com um aplicativo Flask em execução no Docker. Os trabalhadores estavam reiniciando infinitamente com um ID de processo crescente.
image

O problema era relacionado à memória para mim, quando eu aumentei a memória permitida para o Docker, os trabalhadores geraram de forma eficaz.
image

@tilgovi , não me importo se você gostaria de incorporar minhas mudanças em suas relações públicas desde que você chegou lá primeiro. Isso cobrirá os trabalhadores sendo mortos por meio de sinais.

@mildebrandt Vou dar uma olhada, obrigado!

Também estou vendo esse comportamento repentinamente, usando Gunicorn (20.0.4) + Gevent (1.5.0) + Flask dentro de um contêiner do Docker.

[  328.699160] gunicorn[5151]: segfault at 78 ip 00007fc1113c16be sp 00007ffce50452a0 error 4 in _greenlet.cpython-37m-x86_64-linux-gnu.so[7fc11138d000+3e000]

No meu caso, como você pode ver, o segfault está sendo causado por gevent. O que é estranho é que este contêiner funcionou bem 5 dias atrás, e nenhuma das mudanças de código desde então alterou qualquer versão de qualquer uma das bibliotecas, e todas elas estão configuradas para versões específicas. Eu removi o flask-mail como uma dependência, o que pode ter alterado ligeiramente as versões de outras dependências.

Atualizar de gevent == 1.5.0 para gevent == 20.9.0 resolveu o problema para mim.

@ifiddes, seu problema provavelmente não está relacionado. Você está vendo um problema de compatibilidade de ABI entre versões antigas do gevent com o greenlet da versão mais recente. Veja https://github.com/python-greenlet/greenlet/issues/178

Ah, obrigado @jamadden. Esta postagem foi tudo o que pude encontrar ao pesquisar por spawning infinito de workers de inicialização, mas esse problema e o momento desse problema se encaixam no meu problema.

Tive um erro semelhante com uma nova máquina AWS com Ubuntu 20.04 Server e com o mesmo código que funciona em produção.

A máquina foi configurada usando o Ansible como as outras máquinas de produção.

[2020-10-15 15:11:49 +0000] [18068] [DEBUG] Current configuration:
  config: None
  bind: ['127.0.0.1:8000']
  backlog: 2048
  workers: 1
  worker_class: uvicorn.workers.UvicornWorker
  threads: 1
  worker_connections: 1000
  max_requests: 0
  max_requests_jitter: 0
  timeout: 30
  graceful_timeout: 30
  keepalive: 2
  limit_request_line: 4094
  limit_request_fields: 100
  limit_request_field_size: 8190
  reload: False
  reload_engine: auto
  reload_extra_files: []
  spew: False
  check_config: False
  preload_app: False
  sendfile: None
  reuse_port: False
  chdir: /var/www/realistico/app
  daemon: False
  raw_env: []
  pidfile: None
  worker_tmp_dir: None
  user: 1001
  group: 1001
  umask: 0
  initgroups: False
  tmp_upload_dir: None
  secure_scheme_headers: {'X-FORWARDED-PROTOCOL': 'ssl', 'X-FORWARDED-PROTO': 'https', 'X-FORWARDED-SSL': 'on'}
  forwarded_allow_ips: ['127.0.0.1']
  accesslog: /var/www/realistico/logs/gunicorn/access.log
  disable_redirect_access_to_syslog: False
  access_log_format: %(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s"
  errorlog: /var/www/realistico/logs/gunicorn/error.log
  loglevel: debug
  capture_output: False
  logger_class: gunicorn.glogging.Logger
  logconfig: None
  logconfig_dict: {}
  syslog_addr: udp://localhost:514
  syslog: False
  syslog_prefix: None
  syslog_facility: user
  enable_stdio_inheritance: False
  statsd_host: None
  dogstatsd_tags: 
  statsd_prefix: 
  proc_name: None
  default_proc_name: realistico.asgi:application
  pythonpath: None
  paste: None
  on_starting: <function OnStarting.on_starting at 0x7f7ba5fdd550>
  on_reload: <function OnReload.on_reload at 0x7f7ba5fdd670>
  when_ready: <function WhenReady.when_ready at 0x7f7ba5fdd790>
  pre_fork: <function Prefork.pre_fork at 0x7f7ba5fdd8b0>
  post_fork: <function Postfork.post_fork at 0x7f7ba5fdd9d0>
  post_worker_init: <function PostWorkerInit.post_worker_init at 0x7f7ba5fddaf0>
  worker_int: <function WorkerInt.worker_int at 0x7f7ba5fddc10>
  worker_abort: <function WorkerAbort.worker_abort at 0x7f7ba5fddd30>
  pre_exec: <function PreExec.pre_exec at 0x7f7ba5fdde50>
  pre_request: <function PreRequest.pre_request at 0x7f7ba5fddf70>
  post_request: <function PostRequest.post_request at 0x7f7ba5f6e040>
  child_exit: <function ChildExit.child_exit at 0x7f7ba5f6e160>
  worker_exit: <function WorkerExit.worker_exit at 0x7f7ba5f6e280>
  nworkers_changed: <function NumWorkersChanged.nworkers_changed at 0x7f7ba5f6e3a0>
  on_exit: <function OnExit.on_exit at 0x7f7ba5f6e4c0>
  proxy_protocol: False
  proxy_allow_ips: ['127.0.0.1']
  keyfile: None
  certfile: None
  ssl_version: 2
  cert_reqs: 0
  ca_certs: None
  suppress_ragged_eofs: True
  do_handshake_on_connect: False
  ciphers: None
  raw_paste_global_conf: []
  strip_header_spaces: False
[2020-10-15 15:11:49 +0000] [18068] [INFO] Starting gunicorn 20.0.4
[2020-10-15 15:11:49 +0000] [18068] [DEBUG] Arbiter booted
[2020-10-15 15:11:49 +0000] [18068] [INFO] Listening at: unix:/run/gunicorn.sock (18068)
[2020-10-15 15:11:49 +0000] [18068] [INFO] Using worker: uvicorn.workers.UvicornWorker
[2020-10-15 15:11:49 +0000] [18080] [INFO] Booting worker with pid: 18080
[2020-10-15 15:11:49 +0000] [18068] [DEBUG] 1 workers
[2020-10-15 15:11:51 +0000] [18083] [INFO] Booting worker with pid: 18083
[2020-10-15 15:11:53 +0000] [18086] [INFO] Booting worker with pid: 18086
...
[2020-10-15 15:12:09 +0000] [18120] [INFO] Booting worker with pid: 18120
[2020-10-15 15:12:11 +0000] [18123] [INFO] Booting worker with pid: 18123

Depois de muito tempo perdido tentando resolver esse problema sem sucesso (e sem erros nos logs), tentei com este Hello world e encontrei este erro:

ModuleNotFoundError: No module named 'httptools'

Depois de instalar httptools o aplicativo Hello world funciona bem e, inesperadamente, também funciona meu aplicativo.

Não tenho ideia de por que o erro não foi registrado ou por que essa biblioteca foi instalada nas outras máquinas, mas não na nova, mas isso corrigiu o problema para mim.

Se isso tivesse acontecido recentemente e derrubado o nó do kubernetes em que ele estava, consumindo toda a CPU. Graças à dica sobre dmesg acabei encontrando um erro:

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

No final, meu problema era outra instância de https://github.com/python-greenlet/greenlet/issues/178 e foi resolvido atualizando gunicorn, gevent e greenlet para a versão mais recente.

Como esses tipos de exceções não criam logs do Python, não podem ser capturados, retorne o código de saída 0 e pode travar a máquina quando ocorrerem, são muito difíceis de gerenciar.

Eu proponho que o gunicorn detecte um rápido crash-looping desta natureza e

talvez max_consecutive_startup_crashes com o padrão sendo num_workers * 10?

Vamos rastrear a solicitação de recurso de loop de falha no # 2504. Também temos o PR para registro adicional em # 2315. Encerrarei este problema, pois parece que todos já depuraram seus problemas e agora temos algumas solicitações de recursos e melhorias para ajudar outras pessoas no futuro. Obrigado a todos!

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