Solicitações lentas no servidor Flask local

87

Estou começando a brincar com o Flask em um servidor local e estou percebendo que os tempos de solicitação / resposta estão mais lentos do que acho que deveriam ser.

Apenas um servidor simples como o seguinte leva cerca de 5 segundos para responder.

from flask import Flask

app = Flask(__name__)

@app.route("/")
def index():
    return "index"

if __name__ == "__main__":
    app.run()

Alguma ideia? Ou é apenas assim que o servidor local é?

Meroon
fonte
Não é o servidor local, mas pode ter a ver com outros aplicativos em execução em segundo plano em qual sistema operacional você está executando isso?
gabeio
Estou executando o OS X 10.7 em um iMac i7
Meroon
1
Não deve demorar tanto para suas respostas, mas eu realmente mexi com o frasco antes, sem sucesso, aconselharia Bottlepy . Embora ainda verifique seus processos em segundo plano, você pode ter uma versão mais antiga de seu servidor em execução em segundo plano assumindo o controle de seu python e causando suas respostas lentas. Também poderia ser o seu navegador, isso acontece no Chrome & Safari?
gabeio
2
A resposta de @Meroon foi correta para mim. Em vez de alterar as configurações do host, no entanto: Posso recomendar simplesmente usar 127.0.0.1 em vez de localhost? Isso resolveu o problema sem alterar a configuração do sistema.
David Bernat de

Respostas:

93

Ok, eu descobri. Parece ser um problema com o Werkzeug e os sistemas operacionais que oferecem suporte ao ipv6.

Do site Werkzeug http://werkzeug.pocoo.org/docs/serving/ :

Em sistemas operacionais que suportam ipv6 e o ​​têm configurado, como sistemas Linux modernos, OS X 10.4 ou superior, bem como Windows Vista, alguns navegadores podem ser extremamente lentos se acessarem seu servidor local. A razão para isso é que às vezes “localhost” está configurado para estar disponível em socktes ipv4 e ipv6 e alguns navegadores tentarão acessar ipv6 primeiro e depois ivp4.

Portanto, a correção é desativar o ipv6 do localhost comentando a seguinte linha do meu arquivo hosts:

::1             localhost 

Depois de fazer isso, os problemas de latência desaparecem.

Estou realmente curtindo o Flask e fico feliz que não seja um problema com o framework. Eu sabia que não poderia ser.

Meroon
fonte
Muito obrigado! de repente, o teste de desenvolvimento está rápido e responsivo! minha única pergunta: como o arquivo hosts do Mac indica que a remoção do localhost pode afetar as operações do meu Mac, eu me pergunto se ela está se referindo a esta linha (ou aquela que simplesmente localiza localhost em 127.0.0.1
David B.
no meu sistema Windows 10, no arquivo hosts, ambas as entradas (ip4 e ip6) estão comentadas; eles são resolvidos pelo sistema DNS. Tive um grande aumento de velocidade quando executei o servidor em "127.0.0.1" em vez de "localhost" (de 2,0 a 0,003 segundos para chamadas simples)
Lars
Obrigado por esta resposta! Embora minha situação fosse um pouco diferente (comparando o nose2 com o aiosmtpd), sua resposta me deu uma dica: Quando eu desabilito o IPv6 em meu laptop com Windows 10, acelera coisas como 10x ou 100x !!
pepoluan
87

Adicione "threaded = True" como um argumento para app.run (), conforme sugerido aqui: http://arusahni.net/blog/2013/10/flask-multithreading.html

Por exemplo: app.run(host="0.0.0.0", port=8080, threaded=True)

A solução de desativação de ipv6 não funcionou para mim, mas funcionou.

Sajid Siddiqi
fonte
5
Passar --threadedpara o meu manage.pyuso Flask-Scripttambém funcionou.
Snorfalorpagus
7
Para aqueles que conseguiram "consertar" com a ativação de threads, estejam avisados! Neste caso, o atraso foi causado porque a solicitação anterior não foi fechada corretamente, então agora ele está apenas empilhando muitos threads .
kbtz
Obrigado, senhor, por fazer meu localhost rodar incrivelmente rápido.
Benjaminz
@snolflake: Existe uma maneira de saber se as solicitações não estão sendo fechadas corretamente?
Kylotan de
1
Usei a linha de comando flask run --with-threadsque resolveu meu problema.
arno_v
13

A solução de @ sajid-siddiqi é tecnicamente correta, mas tenha em mente que o servidor WSGI embutido em Werkzeug (que é empacotado no Flask e para o que ele serve app.run()) é apenas de thread único.

Instale um servidor WSGI para poder lidar com o comportamento multithread. Fiz muitas pesquisas sobre vários desempenhos de servidores WSGI . Suas necessidades podem variar, mas se tudo o que você está usando é o Flask , eu recomendaria um dos seguintes servidores da web.

Atualização (2020-07-25): Parece que o gevent começou a oferecer suporte ao python3 5 anos atrás, logo depois que comentei que não, então você pode usar o gevent agora.

gevent

Você pode instalar gevent por meio de pip com o comando pip install geventou pip3 com o comando pip3 install gevent. As instruções sobre como modificar seu código de acordo estão aqui: https://flask.palletsprojects.com/en/1.1.x/deploying/wsgi-standalone/#gevent

Meinheld

gevent é melhor, mas de todos os benchmarks que observei que envolvem testes do mundo real, meinheld parece ser o servidor WSGI mais direto e simplista . (Você também pode dar uma olhada no uWSGI se não se importar com mais configurações.)

Você também pode instalar o meinheld por meio do pip3 com o comando pip3 install meinheld. A partir daí, observe o exemplo fornecido na fonte meinheld para integrar o Flask : https://github.com/mopemope/meinheld/blob/master/example/flask_sample.py

* NOTA: Do meu uso do PyCharm , a linha é from meinheld import serverdestacada como um erro, mas o servidor será executado, portanto, você pode ignorar o erro.

mikeho
fonte
Tive grandes problemas de desempenho com o Flask, mesmo as solicitações mais simples demoravam cerca de 0,5s para serem concluídas. Acabei de mudar para gevent e tudo funciona perfeitamente, obrigado!
gronostaj
7

Em vez de ligar para http://localhost:port/endpointligar http://127.0.0.1:port/endpoint. Isso removeu o atraso inicial de 500 ms para mim.

LangeTreeDorpie
fonte
para mim, ele removeu algo como 3 segundos (mudei do formulário 0.0.0.0 para 127.0.0.1). Alguém pode explicar por que e como funciona?
Rotkiv
Por que em nome de Deus isso funciona? Foi de 2,06 segundos para 0,002 segundos. O navegador pode usar o localhost sem problemas, mas o requests.get no localhost leva 2 segundos para ser resolvido.
Xevion
7

Meu problema foi resolvido por "threaded = True", mas quero fornecer algumas informações básicas para distinguir meu problema de outros para os quais isso pode não funcionar.

  1. Meu problema surgiu apenas ao executar o Flask com python3. Mudando para python2, não tive mais esse problema.
  2. Meu problema se manifestou apenas ao acessar a api com o Chrome, ponto em que o Chrome exibiu a tela esperada, mas todo o resto travou (curl, ffx, etc) até que eu recarreguei ou fechei a guia do Chrome, momento em que tudo o mais que estava esperando ao redor retornou um resultado.

Meu melhor palpite é que o Chrome estava tentando manter a sessão aberta e o Flask estava bloqueando as solicitações subsequentes. Assim que a conexão do Chrome foi interrompida ou redefinida, todo o resto foi processado.

No meu caso, o threading corrigiu isso. Claro, agora estou percorrendo alguns dos links que outras pessoas forneceram para ter certeza de que isso não causará nenhum outro problema.

ChePazzo
fonte
4

threaded=Truefunciona para mim, mas finalmente descobri que o problema é devido ao foxyproxy no firefox. Desde quando o aplicativo Flask está em execução no host local, a resposta lenta acontece se

  • foxyproxy está habilitado no firefox

resposta lenta não acontecerá se

  • foxyproxy está desabilitado no firefox

  • acesse o site usando outros navegadores

A única solução que encontrei foi desabilitar o foxyproxy, tentei adicionar localhost à lista negra de proxy e ajustar as configurações, mas nada funcionou.

Edward
fonte
2

Usei a resposta de Miheko para resolver meu problema.

::1 localhostjá estava comentado no meu arquivo hosts e a configuração Threaded=truenão funcionou para mim. Cada solicitação REST demorava 1 segundo para ser processada em vez de ser instantânea.

Estou usando o python 3.6 e consegui que o flask fosse rápido e responsivo às solicitações REST, fazendo com que o flask usasse gevent como seu WSGI.

Para usar gevent, instale-o com pip install gevent

Depois, usei https://gist.github.com/viksit/b6733fe1afdf5bb84a40#file-async_flask-py-L41 para definir o frasco para usar gevent.

Caso o link caia, aqui estão as partes importantes do script:

from flask import Flask, Response
from gevent.pywsgi import WSGIServer
from gevent import monkey

# need to patch sockets to make requests async
# you may also need to call this before importing other packages that setup ssl
monkey.patch_all()

app = Flask(__name__) 


# define some REST endpoints... 

def main():

    # use gevent WSGI server instead of the Flask
    # instead of 5000, you can define whatever port you want.
    http = WSGIServer(('', 5000), app.wsgi_app) 

    # Serve your application
    http.serve_forever()


if __name__ == '__main__':
    main()
Ali Mizan
fonte
threaded = True não está funcionando para (usando python 3.6.7 e postman), estou recebendo VersionConflict: (greenlet 0.4.13 (c: \ anaconda3 \ lib \ site-packages), Requirement.parse ('greenlet> = 0.4. 14; platform_python_implementation == "CPython" ')), posso saber como resolver isso, Obrigado
hanzgs
0

Recebi este erro ao executar em hosts diferentes de localhosttambém, portanto, para alguns, diferentes problemas subjacentes podem exibir os mesmos sintomas.

Troquei a maioria das coisas que tenho usado para Tornado e, de forma anedótica, ajudou bastante. Tive alguns carregamentos de página lentos, mas as coisas geralmente parecem mais responsivas. Além disso, muito anedótico, mas pareço notar que Flask sozinho vai ficar lento com o tempo, mas Flask + Tornado menos. Eu imagino usar o Apache e mod_wsgitornaria as coisas ainda melhores, mas o Tornado é realmente simples de configurar (veja http://flask.pocoo.org/docs/deploying/others/ ).

(Além disso, uma pergunta relacionada: Flask app ocasionalmente travando )

gatoatigrado
fonte
0

Eu tive uma solução diferente aqui. Acabei de deletar tudo .pycdo diretório do servidor e iniciei novamente. A propósito, localhost já foi comentado no meu arquivo hosts (Windows 8).

O servidor estava travando o tempo todo e agora está funcionando bem novamente.

Erickrf
fonte