es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

¿Cómo se encolan las solicitudes en FastAPI/Gunicorn?

Intento entender cómo FastAPI/Gunicorn maneja y encola solicitudes.

Contrato del cliente: una vez que el cliente envía una solicitud, necesita recibir una respuesta en 5 segundos. Si el cliente no recibe una respuesta dentro de 5 segundos, la solicitud ya no es útil y el cliente deja de escuchar la respuesta.

Escenario: considere el siguiente escenario:
1. Supongamos que tenemos 4 trabajadores (usando Gunicorn como administrador de procesos con UvicornWorkers; usando la imagen de docker de tiangolo)
2. El cliente envía 100 solicitudes concurrentes
3. Cada solicitud tarda 5 segundos en completarse
4. Procesamos las primeras 4 solicitudes en 5 segundos
5. Pero para ese momento, las 96 solicitudes restantes aceptadas en la cola (no estoy seguro de si ocurre la encolación o cómo funciona, agradecería si pudiera explicarlo) ya han pasado 5 segundos allí y violaron el contrato del cliente. Procesar estas 96 solicitudes es un desperdicio de recursos ya que el cliente ya no las está escuchando.

Pregunta:
1. ¿Cómo descarto estas 96 solicitudes, es decir, si cada solicitud ha estado esperando más de 5 segundos en la cola, las elimino?

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Para implementar el requisito de descartar solicitudes que han esperado en la cola durante más de 5 segundos, podemos usar una combinación del soporte asincrónico de FastAPI y la configuración de tiempo de espera del trabajador de Gunicorn.

    En primer lugar, podemos establecer un tiempo de espera para los trabajadores de Gunicorn usando la bandera --timeout. Por ejemplo, si queremos que un trabajador tenga tiempo de espera de 5 segundos (para que coincida con el contrato del cliente), podemos establecer --timeout 5.

    A continuación, podemos agregar un middleware a nuestra aplicación FastAPI que verifique el tiempo transcurrido desde que se aceptó la solicitud (es decir, ingresó a la cola), y si supera los 5 segundos, cancele la solicitud levantando una excepción. Por ejemplo, podemos usar la biblioteca async_timeout y el RequestResponseEndpoint de fastapi.dependency_utils para lograr esto:

    import asyncio
    import async_timeout
    from fastapi import FastAPI, Request
    from fastapi.dependency_utils import RequestResponseEndpoint
    
    app = FastAPI()
    
    # un middleware que cancela solicitudes que han esperado demasiado tiempo en la cola
    @app.middleware("http")
    async def enforce_timeout(request: Request, call_next: RequestResponseEndpoint) -> Response:
        try:
            async with async_timeout.timeout(5):
                response = await call_next(request)
        except asyncio.TimeoutError:
            raise HTTPException(status_code=408, detail="Tiempo de espera de solicitud agotado")
        return response
    

    Con este middleware, cualquier solicitud que haya estado esperando en la cola durante más de 5 segundos se cancelará con una respuesta de error HTTP 408 Tiempo de espera de solicitud agotado.

    Tenga en cuenta que para que esto funcione de manera efectiva, debemos configurar a los trabajadores de Gunicorn para que usen tipos de trabajadores asincrónicos (por ejemplo, uvicorn.workers.UvicornWorker) para que el administrador de contexto asíncrono del middleware pueda funcionar correctamente. Además, debemos ajustar el número máximo de trabajadores concurrentes (es decir, el número de banderas --workers pasadas a Gunicorn) en función del tiempo de procesamiento promedio de la solicitud y la cantidad de núcleos de CPU disponibles en la máquina de alojamiento, para que podamos asegurarnos de que el tamaño de la cola sea manejable y el riesgo de tiempos de espera se minimice.

Comments are closed.