Si vous créez un serveur Web avec aiohttp et que vous souhaitez exécuter un processus légèrement lourd lors de la réception d'une requête HTTP [^ job], si vous exécutez le processus tel quel, il sera lent à renvoyer une réponse HTTP, et comme une erreur de temporisation côté client Il peut être traité. Que faire si vous n'avez pas besoin de renvoyer le résultat du traitement et que vous souhaitez renvoyer une réponse HTTP pour mettre fin à la communication HTTP, puis effectuer un processus légèrement plus lourd?
write_eof
</ del>** J'ai trouvé cette méthode pas bonne, alors voyez le post-scriptum. ** **
from asyncio import sleep
from aiohttp import web
async def handler(request):
response = web.Response()
await response.prepare(request)
await response.write_eof()
await sleep(1) #Traitement après renvoi d'une réponse
app = web.Application()
app.router.add_get('/', handler)
if __name__ == '__main__':
web.run_app(app)
Si rien n'est spécifié lors de la création de l'objet Response, le code d'état HTTP est 200.
Avec la méthode ci-dessus, si la connexion est maintenue pendant un certain temps avec keep-alive, cela fonctionne sans problème, donc je ne l'ai pas remarqué, mais en gros cela ne fonctionne pas bien.
Si vous essayez de désactiver la fonction Keep-Alive en ajoutant Connection: close
à l'en-tête de la réponse, vous pouvez voir que le traitement asynchrone suivant n'est pas exécuté au moment de write_eof ()
.
Apparemment, lorsque la connexion avec le client est interrompue, le traitement du gestionnaire de requêtes y est arrêté. (C'était difficile à savoir car il n'y avait pas de message d'erreur)
Référence: https://github.com/aio-libs/aiohttp/issues/4773
Comme solution, il semble préférable d'utiliser aiojobs.
from asyncio import sleep
from aiohttp import web
import aiojobs.aiohttp as aiojobs
async def job():
"""Le processus que vous souhaitez exécuter après avoir renvoyé une réponse"""
await sleep(1)
async def handler(request):
await aiojobs.spawn(request, job())
return web.Response(text='ok')
app = web.Application()
app.router.add_get('/', handler)
aiojobs.setup(app)
if __name__ == '__main__':
web.run_app(app)
Recommended Posts