Erro de tempo limite do trabalhador Gunicorn

182

Eu configurei o gunicorn com 3 trabalhadores e 30 conexões de trabalhador e usando a classe de trabalhador do eventlet. Está configurado atrás do Nginx. Após algumas solicitações, vejo isso nos logs.

[ERROR] gunicorn.error: WORKER TIMEOUT (pid:23475)
None
[INFO] gunicorn.error: Booting worker with pid: 23514

Por que isso está acontecendo? Como posso descobrir o que está errado?

obrigado

John
fonte
2
Você conseguiu resolver o problema? Por favor, compartilhe seus pensamentos, como eu também fiquei com ele. Gunicorn==19.3.1egevent==1.0.1
Black_Rider 20/05
2
Encontrei a solução para isso. Aumento de tempo limite para valor muito grande e então eu era capaz de ver rastreamento de pilha
Black_Rider

Respostas:

156

Tivemos o mesmo problema usando o Django + nginx + gunicorn. A partir da documentação do Gunicorn, configuramos o tempo limite normal que quase não fez diferença.

Após alguns testes, encontramos a solução, o parâmetro a ser configurado é: timeout (E não o tempo limite normal). Funciona como um relógio ..

Então faz:

1) abra o arquivo de configuração do gunicorn

2) defina o TIMEOUT para o que você precisar - o valor está em segundos

NUM_WORKERS=3
TIMEOUT=120

exec gunicorn ${DJANGO_WSGI_MODULE}:application \
--name $NAME \
--workers $NUM_WORKERS \
--timeout $TIMEOUT \
--log-level=debug \
--bind=127.0.0.1:9000 \
--pid=$PIDFILE
Amit Talmor
fonte
9
Obrigado, esta é a resposta certa. E então, para economizar recursos com muitas conexões simultâneas:, em pip install geventseguida, worker_class geventno seu arquivo de configuração ou -k geventna linha de comando.
precisa saber é o seguinte
2
Estou rodando com o supervisor, então o adicionei ao conf.d / app.conf :command=/opt/env_vars/run_with_env.sh /path/to/environment_variables /path/to/gunicorn --timeout 200 --workers 3 --bind unix:/path/to/socket server.wsgi:application
lukik
31

No Google Cloud, basta adicionar --timeout 90ao ponto de entrada emapp.yaml

entrypoint: gunicorn -b :$PORT main:app --timeout 90
Apoorv Agarwal
fonte
21

Execute Gunicorn com --log-level=DEBUG.

Ele deve fornecer um rastreamento da pilha de aplicativos.

gwik
fonte
41
Isso não acontece no meu caso.
Joe
16
é agora--log-level debug
psychok7
4
Eu adoraria obter um rastreio, mas nenhum deles funciona aqui, usando o gunicorn 19.4.5. O material de depuração é exibido, então eu acho que a bandeira foi reconhecida, mas não o rastreamento de pilha no tempo limite.
orzel
6

Você precisa usar uma outra classe de tipo de trabalhador, uma assíncrona como gevent ou tornado. Veja isso para obter mais explicações: Primeira explicação:

Você também pode instalar o Eventlet ou Gevent se espera que o código do aplicativo precise ser pausado por longos períodos de tempo durante o processamento da solicitação

O segundo :

Os trabalhadores síncronos padrão assumem que seu aplicativo é vinculado a recursos em termos de CPU e largura de banda da rede. Geralmente, isso significa que seu aplicativo não deve fazer nada que leve um tempo indefinido. Por exemplo, uma solicitação para a internet atende a esse critério. Em algum momento, a rede externa falhará de tal maneira que os clientes se acumularão nos seus servidores.

Dseed
fonte
Como eu realmente utilizaria uma classe de trabalhadores tão diferente?
Frederick Nord
6

Eu tive um problema muito parecido, também tentei usar o "runserver" para ver se encontrava alguma coisa, mas tudo o que tinha era uma mensagem Killed

Por isso, pensei que poderia haver um problema de recursos, e fui em frente para dar mais RAM à instância, e funcionou.

James Lin
fonte
1
Eu estava vendo esse problema com mesmo com GEvent eo conjunto de tempo limite corretamente, sem memória era o problema
bcattle
6

WORKER TIMEOUTsignifica que seu aplicativo não pode responder à solicitação em um período de tempo definido. Você pode definir isso usando as configurações de tempo limite do gunicorn . Alguns aplicativos precisam de mais tempo para responder do que outro.

Outra coisa que pode afetar isso é escolher o tipo de trabalhador

Os trabalhadores síncronos padrão assumem que seu aplicativo está vinculado a recursos em termos de CPU e largura de banda da rede. Geralmente, isso significa que seu aplicativo não deve fazer nada que leve um tempo indefinido. Um exemplo de algo que leva um tempo indefinido é uma solicitação para a Internet. Em algum momento, a rede externa falhará de tal maneira que os clientes se acumularão nos seus servidores. Portanto, nesse sentido, qualquer aplicativo Web que faça solicitações de saída para APIs se beneficiará de um trabalhador assíncrono.

Quando tive o mesmo problema que o seu (estava tentando implantar meu aplicativo usando o Docker Swarm), tentei aumentar o tempo limite e usar outro tipo de classe de trabalho. Mas tudo falhou.

E, de repente, percebi que estava limitando meu recurso muito baixo para o serviço dentro do meu arquivo de composição. Esta é a coisa que atrasou a aplicação no meu caso

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

Então, sugiro que você verifique o que está diminuindo a velocidade do seu aplicativo.

hashlash
fonte
4

Esse ponto de extremidade está demorando muito?

Talvez você esteja usando o balão sem suporte assíncrono, para que cada solicitação bloqueie a chamada. Para criar suporte assíncrono sem dificultar, adicione o geventtrabalhador.

Com o gevent, uma nova chamada gerará um novo segmento, e o aplicativo poderá receber mais solicitações

pip install gevent
gunicon .... --worker-class gevent
Ramon Medeiros
fonte
1
ajuste simples .. salvou o meu dia!
penduDev
3

Eu tenho o mesmo problema no Docker.

No Docker, mantenho o LightGBMmodelo treinado + Flaskatendendo solicitações. Como servidor HTTP eu usei gunicorn 19.9.0. Quando executo meu código localmente no laptop Mac, tudo funcionou perfeitamente, mas quando executei o aplicativo no Docker, minhas solicitações POST JSON estavam congelando por algum tempo, então o gunicorntrabalhador falhou com [CRITICAL] WORKER TIMEOUTexceção.

Tentei várias abordagens diferentes, mas a única que resolveu meu problema foi a adição worker_class=gthread.

Aqui está minha configuração completa:

import multiprocessing

workers = multiprocessing.cpu_count() * 2 + 1
accesslog = "-" # STDOUT
access_log_format = '%(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(q)s" "%(D)s"'
bind = "0.0.0.0:5000"
keepalive = 120
timeout = 120
worker_class = "gthread"
threads = 3
Artem Zaika
fonte
votou algumas de suas outras respostas também, mas essa não é suficiente: P
Achala Dissanayake
1

timeout é um parâmetro chave para esse problema.

no entanto, não é adequado para mim.

Descobri que não há erro de tempo limite do gunicorn ao definir trabalhadores = 1.

Quando eu olho para o meu código, eu encontrei algum socket connect (socket.send & socket.recv) no init do servidor.

O socket.recv bloqueará meu código e é por isso que ele sempre excede o tempo limite quando trabalhadores> 1

espero dar algumas idéias para as pessoas que têm algum problema comigo

Mao
fonte
1

Isso funcionou para mim:

gunicorn app:app -b :8080 --timeout 120 --workers=3 --threads=3 --worker-connections=1000

Se você eventletadicionou:

--worker-class=eventlet

Se você geventadicionou:

--worker-class=gevent
Skerrepy
fonte
0

Para mim, a solução foi adicionar --timeout 90ao meu ponto de entrada, mas não estava funcionando porque eu tinha DOIS pontos de entrada definidos, um no app.yaml e outro no meu Dockerfile. Eu apaguei o ponto de entrada não utilizado e adicionei --timeout 90no outro.

PV
fonte