J'ai été bricolage autour Flask et Fastapi pour voir comment il agit en tant que serveur.
[.____] L'une des principales choses que je voudrais savoir est de savoir comment Flask et Fastapi traite avec plusieurs demandes de plusieurs clients.
[.____] Surtout lorsque le code a des problèmes d'efficacité (temps de requête de la base de données longue).
Donc, j'ai essayé de faire un code simple pour comprendre ce problème.
[.____] Le code est simple, lorsqu'un client accède à l'itinéraire, l'application peut accueillir pendant 10 secondes avant de renvoyer un résultat.
[.____] Cela ressemble à quelque chose comme ça:
Fastapi
import uvicorn
from fastapi import FastAPI
from time import sleep
app = FastAPI()
@app.get('/')
async def root():
print('Sleeping for 10')
sleep(10)
print('Awake')
return {'message': 'hello'}
if __name__ == "__main__":
uvicorn.run(app, Host="127.0.0.1", port=8000)
Flacon
from flask import Flask
from flask_restful import Resource, Api
from time import sleep
app = Flask(__name__)
api = Api(app)
class Root(Resource):
def get(self):
print('Sleeping for 10')
sleep(10)
print('Awake')
return {'message': 'hello'}
api.add_resource(Root, '/')
if __name__ == "__main__":
app.run()
Une fois que les applications sont en hausse, j'ai essayé d'y accéder simultanément sur 2 à 2 différents chrome Clients. Les résultats ci-dessous sont les résultats:
Fastapi
Entrez la description de l'image ici
Flacon
Entrez la description de l'image ici
Comme vous pouvez le constater, pour Fastapi, le code attend d'abord 10 secondes avant de traiter la demande suivante. Alors que pour le flacon, le code traite la demande suivante tandis que le sommeil de 10 secondes se produit toujours.
Malgré un peu de googling, il n'y a pas vraiment une réponse directe sur ce sujet.
[.____] Si quelqu'un a des commentaires qui peuvent éclairer cela, veuillez les déposer dans les commentaires.
Vous êtes tous appréciés. Merci beaucoup pour votre temps.
[~ # ~] Edit [~ # ~] Une mise à jour à ce sujet, j'explore un peu plus et trouvé ce concept de gestionnaire de processus. Par exemple, nous pouvons exécuter Uvicorn à l'aide d'un gestionnaire de processus (Gunicorn). En ajoutant plus de travailleurs, je suis capable d'atteindre quelque chose comme la fiole. Test toujours testé les limites de cela. https://www.uvicorn.org/deployment/
Merci à tous ceux qui ont laissé des commentaires! Appréciez-le.
Vous utilisez la fonction time.sleep()
, dans un point de terminaison async
. time.sleep()
bloque et ne doit jamais être utilisée dans le code asynchrone. Ce que vous devriez utiliser est probablement la fonction asyncio.sleep()
:
import asyncio
import uvicorn
from fastapi import FastAPI
app = FastAPI()
@app.get('/')
async def root():
print('Sleeping for 10')
await asyncio.sleep(10)
print('Awake')
return {'message': 'hello'}
if __name__ == "__main__":
uvicorn.run(app, Host="127.0.0.1", port=8000)
De cette façon, chaque demande prendra environ 10 secondes, mais vous pourrez servir plusieurs demandes simultanément.
En général, les cadres ASYNC offrent des remplacements pour toutes les fonctions de blocage dans la bibliothèque standard (fonctions de veille, IO, etc.). Vous êtes censé utiliser ces remplaçants lors de la rédaction de code ASYNC et (éventuellement). await
eux.
Certains cadres et bibliothèques non bloquants tels que Gevent, n'offrent pas de remplacement. Ils ont à la place des fonctions de correction de singe dans la bibliothèque standard pour les rendre non bloquantes. Ce n'est pas le cas, autant que je sache, pour les nouveaux cadres et bibliothèques asynchrones, car ils sont censés permettre au développeur d'utiliser la syntaxe ASYNC-Await.
Je pense que vous bloquez une file d'attente d'événement dans Fastapi, qui est un cadre asynchrone, alors que In Flask Les demandes sont probablement exécutées chacune dans un nouveau thread. Déplacez toutes les tâches liées à la CPU pour séparer les processus ou dans votre exemple FastAPI. sur la boucle d'événement (n'utilisez pas l'heure.sleep ici). Dans Fastapi Run IO tâches liées de manière asynchrone