¿Puedo servir a varios clientes usando solo Flask app.run () como independiente?
202
Sé que puedo vincular Flask con Apache u otros servidores web. Pero estaba pensando en ejecutar Flask como un servidor independiente que sirve a varios clientes simultáneamente.
es posible? ¿Tengo que manejar el desove de múltiples hilos y administrarlos?
flask.Flask.runacepta argumentos de palabras clave adicionales ( **options) a los que reenvía werkzeug.serving.run_simple; dos de esos argumentos son threaded(un booleano) y processes(que puede establecer en un número mayor que uno para que werkzeug genere más de un proceso para manejar solicitudes).
threadedel valor predeterminado Truees Flask 1.0, por lo que para las últimas versiones de Flask, el servidor de desarrollo predeterminado podrá servir a varios clientes simultáneamente de forma predeterminada. Para versiones anteriores de Flask, puede pasar explícitamente threaded=Truepara habilitar este comportamiento.
Por ejemplo, puedes hacer
if __name__ =='__main__':
app.run(threaded=True)
para manejar múltiples clientes usando hilos de una manera compatible con versiones antiguas de Flask, o
if __name__ =='__main__':
app.run(threaded=False, processes=3)
para decirle a Werkzeug que genere tres procesos para manejar las solicitudes entrantes, o simplemente
if __name__ =='__main__':
app.run()
para manejar múltiples clientes usando hilos si sabe que usará Flask 1.0 o posterior.
Dicho esto, Werkzeug serving.run_simpleenvuelve el wsgirefpaquete de la biblioteca estándar , y ese paquete contiene una implementación de referencia de WSGI, no un servidor web listo para producción. Si va a utilizar Flask en producción (suponiendo que "producción" no sea una aplicación interna de bajo tráfico con no más de 10 usuarios simultáneos) asegúrese de respaldarlo detrás de un servidor web real (consulte la sección de documentos de Flask titulada Opciones de implementación para algunos métodos sugeridos).
¿Qué pasa si estoy viendo un máximo de 100 usuarios? ¿Puedo asignar processes=100y ser feliz con eso? En mi caso, solo necesito archivos estáticos, no hay métodos HTTP Post. Mi requisito es que quiero ejecutar todos los subprocesos de Flask como parte de mi aplicación principal, para que todos puedan compartir variables.
ATOzTOA
44
Risas - @ATOzTOA - no, eso probablemente sería bastante contraproducente (los procesos son relativamente caros, y a menos que esté haciendo mucho trabajo en cada solicitud, no hay razón para que 4 u 8 procesos no sean suficientes). Dicho esto, si solo está mostrando contenido estático, estaría mejor con un servidor que esté optimizado para hacerlo (Apache, ngnix, IIS).
Sean Vieira
2
Además, normalmente no debería necesitar compartir variables entre solicitudes; si lo hace , deberá limitarse a un proceso o utilizar alguna comunicación fuera de banda (Redis, una base de datos, el sistema de archivos, etc.) que cada uno de tus procesos permanezca sincronizado.
Sean Vieira
3
@ATOzTOA: si no puede activar un mejor servidor, simplemente le daré una vuelta y veré qué sucede. Si no funciona bien bajo carga, puede implementarlo detrás de un servidor web diferente.
Sean Vieira
2
@ATOzTOA, con respecto a su pregunta sobre por qué no puede especificar 'hilos' y 'procesos' al mismo tiempo, consulte
pyrho
62
El uso de lo simple app.run()desde Flask crea un único servidor síncrono en un solo hilo capaz de servir solo a un cliente a la vez. Está diseñado para su uso en entornos controlados con baja demanda (es decir, desarrollo, depuración) exactamente por este motivo.
Generar subprocesos y administrarlos usted mismo probablemente tampoco lo llevará muy lejos, debido a Python GIL .
Dicho esto, todavía tienes algunas buenas opciones. Gunicorn es un servidor WSGI sólido y fácil de usar que le permitirá generar múltiples trabajadores (procesos separados, por lo que no se preocupe por GIL), e incluso viene con trabajadores asincrónicos que acelerarán su aplicación (y la harán más segura) con poco a ningún trabajo de su parte (especialmente con Flask).
Aún así, incluso Gunicorn probablemente no debería estar expuesto públicamente directamente. En producción, debe usarse detrás de un servidor HTTP más robusto; nginx tiende a ir bien con Gunicorn y Flask.
no exactamente. Gunicorn es python, nginx no lo es. sin embargo, no es así como los usarías. Gunicorn te dejaría ejecutar tu aplicación como en gunicorn app:app 127.0.0.1:8080lugar de python app.py. Nginx actuaría como el servicio público que expone su aplicación privada ejecutada por Gunicorn (un proxy inverso) , ocultando todo tipo de detalles de implementación HTTP de nivel inferior, tal vez sirviendo archivos estáticos directamente, etc.
processes=100
y ser feliz con eso? En mi caso, solo necesito archivos estáticos, no hay métodos HTTP Post. Mi requisito es que quiero ejecutar todos los subprocesos de Flask como parte de mi aplicación principal, para que todos puedan compartir variables.El uso de lo simple
app.run()
desde Flask crea un único servidor síncrono en un solo hilo capaz de servir solo a un cliente a la vez. Está diseñado para su uso en entornos controlados con baja demanda (es decir, desarrollo, depuración) exactamente por este motivo.Generar subprocesos y administrarlos usted mismo probablemente tampoco lo llevará muy lejos, debido a Python GIL .
Dicho esto, todavía tienes algunas buenas opciones. Gunicorn es un servidor WSGI sólido y fácil de usar que le permitirá generar múltiples trabajadores (procesos separados, por lo que no se preocupe por GIL), e incluso viene con trabajadores asincrónicos que acelerarán su aplicación (y la harán más segura) con poco a ningún trabajo de su parte (especialmente con Flask).
Aún así, incluso Gunicorn probablemente no debería estar expuesto públicamente directamente. En producción, debe usarse detrás de un servidor HTTP más robusto; nginx tiende a ir bien con Gunicorn y Flask.
fuente
gunicorn app:app 127.0.0.1:8080
lugar depython app.py
. Nginx actuaría como el servicio público que expone su aplicación privada ejecutada por Gunicorn (un proxy inverso) , ocultando todo tipo de detalles de implementación HTTP de nivel inferior, tal vez sirviendo archivos estáticos directamente, etc.