Python asynchronous REST API with responses which rely on CPU intensive calculations. How to handle efficiently? [duplicate]

喜欢而已 提交于 2019-12-23 19:10:54

问题


I have written a basic REST API using aiohttp, a simplified version of which is included below to illustrate the problem I am looking to solve.

The API has two endpoints - each of which calls a function that performs some calculations. The difference between the two is that for one of the endpoints, the calculations take 10 seconds, and for the other they take only 1 second.

My code is below (the actual calculations have been replaced with time.sleep() calls).

import time
from aiohttp import web


def simple_calcs():
    time.sleep(1)  # Pretend this is the simple calculations
    return {'test': 123}

def complex_calcs():
    time.sleep(10)  # Pretend this is the complex calculations
    return {'test': 456}


routes = web.RouteTableDef()

@routes.get('/simple_calcs')
async def simple_calcs_handler(request):
    results = simple_calcs()
    return web.json_response(results)

@routes.get('/complex_calcs')
async def complex_calcs_handler(request):
    results = complex_calcs()
    return web.json_response(results)


app = web.Application()
app.add_routes(routes)
web.run_app(app)

What I would like to happen:

If I send a request to the slower endpoint, then immediately afterwards send a request to the faster endpoint, I would like to receive a response from the faster endpoint first while the slower calculations are still ongoing.

What actually happens:

The calculations being carried out by the slower endpoint are blocking. I receive the response from the slow endpoint after ~10 seconds and from the fast endpoint after ~11 seconds.

I've spent the last few hours going round in circles, reading up on asyncio and multiprocessing, but unable to find anything that could solve my problem. Probably I need to spend a bit longer studying this area to gain a better understanding, but hoping I can get a push in the right direction towards the desired outcome.


回答1:


Any blocking IO calls should be avoided in asyncio.

Essentially time.sleep(10) blocks the whole aiohttp server for 10 seconds.

To solve it please use loop.run_in_executor() call:

async def complex_calcs():
    loop = asyncio.get_event_loop()
    loop.run_in_executor(None, time.sleep, 10)  # Pretend this is the complex calculations
    return {'test': 456}


来源:https://stackoverflow.com/questions/52336742/python-asynchronous-rest-api-with-responses-which-rely-on-cpu-intensive-calculat

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!