workers app_module python flask python-requests gunicorn gevent

python - app_module - Realice una solicitud de no bloqueo con solicitudes cuando ejecute Flask con Gunicorn y Gevent



gunicorn timeout configuration (3)

Mi aplicación de Flask recibirá una solicitud, realizará un procesamiento y luego realizará una solicitud a un punto final externo lento que demore 5 segundos en responder. Parece que ejecutar Gunicorn con Gevent le permitirá manejar muchas de estas solicitudes lentas al mismo tiempo. ¿Cómo puedo modificar el siguiente ejemplo para que la vista no se bloquee?

import requests @app.route(''/do'', methods = [''POST'']) def do(): result = requests.get(''slow api'') return result.content

gunicorn server:app -k gevent -w 4


Primero, un poco de fondo, un zócalo de bloqueo es el tipo predeterminado de zócalo, una vez que comienza a leer su aplicación o subproceso, no recupera el control hasta que los datos se leen realmente o se desconecta. Así es como opera python-requests , por defecto. Hay un spin off llamado grequests que proporciona lecturas no bloqueantes.

La principal diferencia mecánica es que el envío, la recepción, la conexión y la aceptación pueden devolverse sin haber hecho nada. Usted tiene (por supuesto) una serie de opciones. Puedes verificar el código de retorno y los códigos de error y, en general, volverte loco. Si no me crees, inténtalo alguna vez.

Fuente: https://docs.python.org/2/howto/sockets.html

También continúa diciendo:

No hay duda de que el código de sockets más rápido usa sockets no bloqueantes y selecciona para multiplexarlos. Puede armar algo que saturará una conexión LAN sin poner presión en la CPU. El problema es que una aplicación escrita de esta manera no puede hacer mucho más que eso: debe estar lista para mezclar los bytes en todo momento.

Suponiendo que se supone que tu aplicación debe hacer algo más que eso, el subprocesamiento es la solución óptima

Pero, ¿quieres agregar un montón de complejidad a tu vista haciendo que genere sus propios hilos? Particularmente cuando gunicorn como async trabajadores ?

Los trabajadores asíncronos disponibles se basan en Greenlets (a través de Eventlet y Gevent). Greenlets es una implementación de subprocesos múltiples cooperativos para Python. En general, una aplicación debe poder hacer uso de estas clases de trabajadores sin cambios.

y

Algunos ejemplos de comportamiento que requieren trabajadores asíncronos: aplicaciones que realizan llamadas de bloqueo prolongadas (es decir, servicios web externos)

Así que para acortar una larga historia, ¡no cambies nada! Sólo deja que sea. Si está realizando algún cambio, deje que sea para introducir el almacenamiento en caché. Considere usar Cache-control una extensión recomendada por los desarrolladores de solicitudes de python.


Puedes usar grequests . Permite que se ejecuten otros greenlets mientras se realiza la solicitud. Es compatible con la biblioteca de requests y devuelve un objeto requests.Response . El uso es el siguiente:

import grequests @app.route(''/do'', methods = [''POST'']) def do(): result = grequests.map([grequests.get(''slow api'')]) return result[0].content

Edición: Agregué una prueba y vi que el tiempo no mejoró con las misiones verdes, ya que el trabajador de gunicorn gevent ya realiza parches de mono cuando se inicia: https://github.com/benoitc/gunicorn/blob/master/gunicorn/workers/ggevent.py#L65


Si está implementando su aplicación Flask con gunicorn, ya no está bloqueado. Si un cliente está esperando una respuesta de una de sus vistas, otro cliente puede realizar una solicitud a la misma vista sin problemas. Habrá múltiples trabajadores para procesar múltiples solicitudes al mismo tiempo. No es necesario cambiar el código para que esto funcione. Esto también se aplica a casi todas las opciones de despliegue de Flask.