Posso atender a vários clientes usando apenas o Flask app.run () como autônomo?

202

Eu sei que posso vincular o Flask ao Apache ou a outros servidores da web. Mas, eu estava pensando em executar o Flask como um servidor independente, atendendo a vários clientes simultaneamente.

Isso é possível? Preciso lidar com a geração de vários threads e gerenciá-los?

ATOzTOA
fonte

Respostas:

295

flask.Flask.runaceita argumentos de palavras-chave adicionais ( **options) que encaminha para werkzeug.serving.run_simple- dois desses argumentos são threaded(um booleano) e processes(que você pode definir para um número maior que um para que o werkzeug gere mais de um processo para lidar com solicitações).

threadedo padrão Trueé o do Flask 1.0; portanto, para as versões mais recentes do Flask, o servidor de desenvolvimento padrão poderá atender a vários clientes simultaneamente por padrão. Para versões mais antigas do Flask, você pode passar explicitamente threaded=Truepara ativar esse comportamento.

Por exemplo, você pode fazer

if __name__ == '__main__':
    app.run(threaded=True)

para lidar com vários clientes usando threads de maneira compatível com as versões antigas do Flask, ou

if __name__ == '__main__':
    app.run(threaded=False, processes=3)

dizer ao Werkzeug para gerar três processos para lidar com solicitações recebidas, ou apenas

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

para lidar com vários clientes usando threads, se você souber que usará o Flask 1.0 ou posterior.

Dito isto, o Werkzeug serving.run_simpleenvolve o wsgirefpacote da biblioteca padrão - e esse pacote contém uma implementação de referência do WSGI, não um servidor Web pronto para produção. Se você usar o Flask em produção (supondo que "produção" não seja um aplicativo interno de baixo tráfego e com mais de 10 usuários simultâneos), mantenha-o atrás de um servidor Web real (consulte a seção de documentos do Flask, intitulada Opções de implantação para alguns métodos sugeridos).

Sean Vieira
fonte
2
E se eu estiver vendo no máximo 100 usuários? Posso apenas atribuir processes=100e ser feliz com isso? No meu caso, eu só preciso de arquivos estáticos, sem métodos HTTP Post. Minha exigência é que eu queira executar todos os threads do Flask como parte do meu aplicativo pai, para que todos possam compartilhar variáveis.
ATOzTOA
4
Chuckles - @ATOzTOA - Não, isso provavelmente seria muito contraproducente (Processos são relativamente caros, ea menos que você está fazendo um monte de trabalho em cada pedido há nenhuma razão para que 4 ou 8 processos não deve ser suficiente). Dito isto, se você estiver exibindo apenas conteúdo estático, seria melhor ter um servidor otimizado para isso (Apache, ngnix, IIS).
45619 Sean Sean Vieira
2
Além disso, você normalmente não precisa compartilhar variáveis ​​entre solicitações - se o fizer , precisará limitar-se a um processo ou usar alguma comunicação fora da banda (Redis, um banco de dados, o sistema de arquivos etc.), para que cada um dos seus processos permaneça sincronizado.
Sean Vieira
3
@ATOzTOA - se você não consegue criar um servidor melhor, eu gostaria de ver o que acontece. Se não funcionar bem sob carga, você pode implantá-lo atrás de um servidor da web diferente.
45619 Sean Sean Vieira
2
@ATOzTOA, quanto à sua pergunta sobre por que você não pode especificar 'rosca' e 'processos', ao mesmo tempo, cf o código aqui: werkzeug.readthedocs.org/en/latest/_modules/werkzeug/serving
pyrho
62

Usar o simple app.run()de dentro do Flask cria um único servidor síncrono em um único thread capaz de atender apenas um cliente por vez. Ele se destina ao uso em ambientes controlados com baixa demanda (ou seja, desenvolvimento, depuração) exatamente por esse motivo.

Gerar threads e gerenciá-los você provavelmente também não o levará muito longe, por causa do Python GIL .

Dito isto, você ainda tem algumas boas opções. O Gunicorn é um servidor WSGI sólido e fácil de usar, que permite gerar vários trabalhadores (processos separados, portanto, não se preocupa com o GIL) e até vem com trabalhadores assíncronos que aceleram seu aplicativo (e o tornam mais seguro) com pouco sem trabalho da sua parte (especialmente com o Flask).

Mesmo assim, Gunicorn provavelmente não deve ser exposto publicamente diretamente. Na produção, ele deve ser usado atrás de um servidor HTTP mais robusto; O nginx costuma ir bem com o Gunicorn e o Flask.

Ryan Artecona
fonte
17
não exatamente. Gunicorn é python, nginx não é. não é assim que você os usaria. O Gunicorn permite que você execute seu aplicativo como em gunicorn app:app 127.0.0.1:8080vez de python app.py. Nginx agiria como o serviço público que expõe seu aplicativo Gunicorn-run privado (a reverse-proxy) , escondendo todos os tipos de baixo nível detalhes de implementação HTTP, talvez servir arquivos estáticos diretamente, etc.
Ryan Artecona
O frasco com app.run (thread = True) roda muito bem no Apache2 usando mod_wsgi flask.palletsprojects.com/en/1.1.x/deploying/mod_wsgi
MortenB