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.

FastAPI responde lentamente al llamarlo a través de otra aplicación de Python, pero rápido en cURL.

Tengo un problema con el que no puedo lidiar. Tengo un servicio API construido con FastAPI, y cuando intento llamar a cualquier punto final desde otro script de Python en mi máquina local, la respuesta demora 2 o más segundos. Cuando envío la misma solicitud a través de cURL o los documentos Swagger integrados, la respuesta es casi instantánea.

El script completo del servidor es el siguiente:

from fastapi import FastAPI
import uvicorn

app = FastAPI()

@app.get("/")
async def root():
    return {"message": "Hello World"}

if __name__ == '__main__':
    uvicorn.run(app, host='0.0.0.0', port=8000)

Luego lo llamo desde un script de prueba usando HTTPX. También lo intenté con el paquete de solicitudes, y es el mismo resultado.

import httpx
r = httpx.get('http://localhost:8000/')
print(r.elapsed)

Esto imprime algo como: 0:00:02.069705

Luego hago lo mismo usando cURL:

curl -w "@curl-format.txt" -o /dev/null -X 'GET' 'http://localhost:8000/'

Esto imprime:

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    32  100    32    0     0    941      0 --:--:-- --:--:-- --:--:--   969
     time_namelookup:  0.006436s
        time_connect:  0.006747s
     time_appconnect:  0.000000s
    time_pretransfer:  0.006788s
       time_redirect:  0.000000s
  time_starttransfer:  0.034037s
                     ----------
          time_total:  0.034093s

El problema no está en lo que hace el punto final, sino en que no comienza a ejecutarse hasta después de 2 segundos. Tengo un depurador ejecutándose en el punto final, y la primera línea se ejecuta solo después de esos 2 segundos.

Intenté inspeccionar la solicitud para ver si hay encabezados u otros elementos similares en la solicitud que podrían ralentizarla, pero no encontré nada. Cuando lo intenté nuevamente con los encabezados generados por HTTPX, todavía se ejecutó rápidamente.

Aquí hay una captura de pantalla de la solicitud en PyCharm, lamentablemente no se puede volcar directamente a JSON.

Estoy empezando a pensar que tiene algo que ver con Uvicorn y cómo ejecuta la aplicación, pero no puedo entender por qué.

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Parece que el problema no está en el código ni en el endpoint en sí, sino en la forma en que el servidor FastAPI se está ejecutando a través de Uvicorn. El tiempo de respuesta al llamar al endpoint desde otro script de Python es lento, tardando alrededor de 2+ segundos, mientras que llamar al mismo endpoint a través de cURL o de los documentos internos de Swagger devuelve la respuesta casi instantáneamente.

    Una posible razón para esto podría ser que el ciclo de eventos se está bloqueando debido a los procesos de trabajo de Uvicorn. Uvicorn utiliza ASGI que ejecuta la aplicación en un estilo asincrónico impulsado por eventos. Si el ciclo de eventos está bloqueado, puede hacer que la aplicación tarde más en ejecutarse o responder a las solicitudes.

    Para resolver este problema, podría intentar aumentar el número de procesos de trabajo en el servidor Uvicorn. Esto se puede hacer usando la bandera --workers al ejecutar el servidor, por ejemplo:

    `
    uvicorn main:app --workers 4
    `

    Esto iniciará 4 procesos de trabajo, que pueden manejar múltiples solicitudes simultáneamente, reduciendo las posibilidades de que el ciclo de eventos se bloquee.

    Otra solución podría ser usar un servidor ASGI diferente, como Daphne, que puede ejecutar la aplicación en múltiples hilos o procesos, permitiendo un mejor rendimiento y tiempos de respuesta más rápidos.

    En general, es importante tener en cuenta las limitaciones y requisitos de ASGI al crear APIs con FastAPI, y elegir una configuración de servidor adecuada que pueda manejar la carga y la concurrencia esperadas de la aplicación.

Comments are closed.