FastAPI : pourquoi les appels d'API sont exécutés en série plutôt qu'en parallèle
FastAPI définit les points de terminaison (également appelés fonctions d'opération de chemin) en utilisant à la fois l'async déf et déf. Bien que conceptuellement, async def puisse suggérer une parallélisation, FastAPI gère en fait ces fonctions différemment :
Points de terminaison définis avec async def :
- Exécuter directement dans la boucle d'événements.
- Ne peut être appelé qu'à partir d'autres fonctions asynchrones et doit faire une pause (attendre) avant d'exécuter des opérations non asynchrones, telles que les E/S.
- Assurez-vous que la boucle d'événements n'est pas bloquée et que d'autres tâches peuvent être exécutées simultanément.
Points de terminaison définis avec def :
- Exécuter pas directement dans la boucle d'événements mais plutôt dans un thread séparé à partir d'un externe threadpool.
- Peut être appelé à partir de fonctions asynchrones ou non asynchrones.
- Peut bloquer la boucle d'événements et empêcher l'exécution d'autres tâches si des opérations non asynchrones sont effectuées sans pause.
- Proposer des optimisations de performances dans certains scénarios.
Impact sur Parallélisation :
Sur la base de cette compréhension, examinons votre exemple de code :
@app.get("/ping")
async def ping(request: Request):
print("Hello")
time.sleep(5) # This sleeps the event loop for 5 seconds
print("bye")
return {"ping": "pong!"}
Copier après la connexion
Dans ce cas, ce qui suit se produit :
- Deux requêtes à /ping sont envoyés simultanément.
- Le defENDPOINT asynchrone s'exécute directement dans l'événement boucle.
- L'appel time.sleep(5) met en pause la boucle d'événements pendant 5 secondes.
- Pendant ces 5 secondes, la deuxième requête est mise en file d'attente et ne peut pas être traitée puisque la boucle d'événements est bloquée .
- Une fois la boucle d'événement reprise au bout de 5 secondes, la deuxième requête est traitée.
En conséquence, les réponses sont imprimées en série :
Hello
bye
Hello
bye
Copier après la connexion
Pour activer la parallélisation, les opérations non asynchrones comme time.sleep() ne devraient pas être utilisées dans les points de terminaison de définition asynchrones. Au lieu de cela, l'une des approches suivantes peut être appliquée :
- Utilisez run_in_threadpool() pour générer un thread et exécuter l'opération de blocage en dehors de la boucle d'événements.
- Utilisez loop.run_in_executor() ou asyncio.to_thread() pour exécuter l'opération de blocage dans un thread ou un processus distinct.
- Envisagez d'utiliser ThreadPoolExecutor ou ProcessPoolExecutor pour exécuter des tâches gourmandes en calcul hors processus.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!