Торнадо одновременно с асинхронным запросом - PullRequest
1 голос
/ 23 мая 2019

Предполагается, что нагрузка на мой веб-сервер составляет около 100 запросов в секунду.и у меня есть 70% запросов, которые связаны с вводом-выводом и выполняют легкую задачу (например, запросы к базе данных), в то время как 30% запросов связаны с процессором, что делает тяжелую задачу (такую ​​как хеширование, вычисления с ресурсами в файловой системе),Последние запросы также являются блокировкой ввода / вывода, поэтому я использую ThreadPoolExecutor, чтобы они не блокировали более быстрые запросы:

@tornado.concurrent.run_on_executor
def post(self, *args):
    # I'm a io blocking request
    data = heavy_load_task()
    self.write(data)

, тогда как 70% запросов выполняются с asynchronous decorator, таким образом запрашивая конкретный вызов self.finish() для явного закрытия сокета:

@tornado.web.asynchronous
def post(self, *args):
    # I'm a light request
    data = light_load_task()
    self.write(data)
    self.finish()

См. здесь о том, как делать неблокирующие запросы в Tornado.В частности, вместо этого используется исполнитель пула потоков по умолчанию, например:

executor = concurrent.futures.ThreadPoolExecutor(5)

Я использую (надеюсь) лучшую реализацию, которая заботится об ограничении числа одновременных потоков, чтобы избежать нагрузки на память:

executor = BoundedThreadPoolExecutor(max_workers=5)

Пожалуйста, смотрите этот пакет для реализации BoundedThreadPoolExecutor.

Кажется, это работает нормально.Из соображений производительности я попытался переместить прежние запросы легких задач из шаблона @tornado.web.asynchronous в шаблон @tornado.concurrent.run_on_executor, и здесь у меня возникла проблема.В какой-то момент сервер перестал обслуживать запросы, без сбоев, без ошибок времени выполнения.Он просто перестал получать запросы и обслуживать ответы с любой ошибкой или проблемой OOM на машине.Я пробовал разные размеры рабочей очереди max_workers от 5 до 100 одновременно работающих без видимого эффекта.

...