问题
I'm trying to use the gaiohttp worker in Gunicorn with a Django app I'm developing with the following command:
gunicorn -k gaiohttp -b localhost:8080 myproject.wsgi
My ultimate goal is to be able to process requests concurrently - i.e. have 1 gunicorn worker process multiple requests concurrently. There are I/O bound operations which makes these requests slow.
I know an event loop is already running when I'm processing a request:
class MyView(View):
def get(self, request):
loop = asyncio.get_event_loop()
loop.is_running() # True
...
Questions:
How can I perform an operation such as
yield from asyncio.sleep(10)
within my view code?class MyView(View): def get(self, request): # Raises AssertionError: yield from wasn't used with future yield from asyncio.sleep(10)
I can add tasks to the event loop, however they don't block while processing the request
@asyncio.coroutine def simulate_work(): yield from asyncio.sleep(10) class MyView(View): def get(self, request): # This runs simulate_work(), however, it doesn't block # the response is returned before simulate_work() is finished loop = asyncio.get_event_loop() task = loop.create_task(simulate_work())
I try to use futures, but the event loop is already running
@asyncio.coroutine def simulate_work(future): yield from asyncio.sleep(10) future.set_result('Done!') class MyView(View): def get(self, request): future = asyncio.Future() asyncio.async(simulate_work(future)) loop = asyncio.get_event_loop() # Raises RuntimeError: Event loop is running. loop.run_until_complete(future) print(future.result())
Clearly there's something I'm not understanding about asyncio or gaiohttp.
How can I have asyncio.sleep(10)
block for the current requests, but not block gunicorn from processing other requests?
回答1:
Sorry, you cannot call coroutines from your wsgi application -- WSGI is synchronous protocol, as well as frameworks built on top of it (Django, Flask, Pyramid).
I've implemented gaiohttp
worker but it's second class citizen in asyncio world. If you really need asynchronous HTTP server please try aiohttp.web.
来源:https://stackoverflow.com/questions/28222429/how-do-i-yield-to-another-request-when-using-gunicorn-with-asyncio