Смешивание торнадо и sqlalchemy - PullRequest
0 голосов
/ 05 ноября 2018

Я пытаюсь написать веб-приложение торнадо, которое использует sqlalchemy в некоторых обработчиках запросов. Эти обработчики состоят из двух частей: одна занимает много времени, а другая использует sqlalchemy и является относительно быстрой. Я хотел бы сделать медленную часть запроса асинхронной, но не часть sqlalchemy. Могу ли я сделать что-то вроде следующего кода и быть в безопасности?

class ExampleHandler(BaseHandler):
    async def post(self):
        loop = asyncio.get_event_loop()
        await loop.run_in_executor(...)   # very slow (no sqlalchemy here)

        with self.db_session() as s:      # sqlalchemy session
            s.add(...)
            s.commit()

        self.render(...)

Идея состоит в том, чтобы sqlalchemy по-прежнему блокировалась, но иметь вычислительную тяжелую часть, не блокирующую приложение.

1 Ответ

0 голосов
/ 12 ноября 2018

Веб-сервер торнадо использует асинхронный код, чтобы обойти ограничение Python Global Interpreter Lock. GIL, как известно в разговорной речи, позволяет выполнять только один поток выполнения в процессе интерпретатора Python. Tornado может отвечать на многие запросы одновременно благодаря использованию цикла обработки событий. Цикл событий может выполнять одну маленькую задачу за раз. Давайте возьмем ваш собственный обработчик сообщений, чтобы лучше это понять.

В этом обработчике, когда интерпретатор python достигает ключевого слова await, он приостанавливает выполнение функции и ставит ее в очередь для последующего цикла обработки событий. Затем он проверяет цикл обработки событий, чтобы ответить на другие события, которые могли там находиться в очереди, такие как ответ на новое соединение или обслуживание другого обработчика.

Когда вы блокируете асинхронную функцию, вы замораживаете весь цикл обработки событий, так как он не может приостановить вашу функцию и обслуживать что-либо еще. На самом деле это означает, что ваш веб-сервер не будет принимать или обслуживать какие-либо запросы, в то время как ваши асинхронные функциональные блоки. Он будет выглядеть так, как будто ваш веб-сервер завис и действительно застрял.

Чтобы сервер отвечал, вы должны найти способ выполнить запрос sqlalchemy асинхронным неблокирующим способом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...