Как я могу уступить другому запросу при использовании пушки с асинчио?

Я пытаюсь использовать gaiohttp worker в Gunicorn с помощью приложения Django, которое я разрабатываю с помощью следующей команды:

gunicorn -k gaiohttp -b localhost:8080 myproject.wsgi

Моя конечная цель состоит в том, чтобы иметь возможность обрабатывать запросы одновременно - т.е. один рабочий-десантник обрабатывает несколько запросов одновременно. Имеются операции с привязкой ввода/вывода, которые замедляют эти запросы.

Я знаю, что цикл обработки уже запущен, когда я обрабатываю запрос:

class MyView(View):

    def get(self, request):
        loop = asyncio.get_event_loop()
        loop.is_running() # True
        ...

Вопросы:

  • Как я могу выполнить операцию, такую ​​как yield from asyncio.sleep(10) внутри моего кода просмотра?

    class MyView(View):
    
        def get(self, request):
            # Raises AssertionError: yield from wasn't used with future
            yield from asyncio.sleep(10)
    
  • Я могу добавить задачи к циклу событий, однако они не блокируют при обработке запроса

    @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())
    
  • Я пытаюсь использовать фьючерсы, но цикл событий уже запущен

    @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())
    

Ясно, что я что-то не понимаю о asyncio или gaiohttp.

Как я могу иметь блок asyncio.sleep(10) для текущих запросов, но не блокировать пушки из обработки других запросов?

Ответ 1

Извините, вы не можете вызывать сопрограммы из вашего приложения wsgi - WSGI - это синхронный протокол, а также встроенные фреймворки (Django, Flask, Pyramid).

Я реализовал рабочий gaiohttp, но это гражданин второго класса в мире асинчо. Если вам действительно нужен асинхронный HTTP-сервер, попробуйте aiohttp.web.