Веб-сервер, встроенный в фляжку, не предназначен для использования в производстве, точно по причинам, которые вы перечисляете, - он однопоточный и легко забит, если какой-либо запрос блокирует для нетривиального количества времени. Футлярная документация lists several options for deploying it in a production environment; mod_wsgi
, gunicorn
, uSWGI
и т. Д. Все эти варианты развертывания предоставляют механизмы для обработки параллелизма либо через потоки, процессы, либо неблокирующие операции ввода-вывода. Однако обратите внимание, что если вы выполняете операции с привязкой к процессору, единственным вариантом, который даст настоящий параллелизм, является использование нескольких процессов.
Если вы хотите использовать tornado
, вам необходимо переписать заявку в стиле tornado
. Поскольку его архитектура основана на явном асинхронном вводе-выводе, вы не можете использовать ее асинхронные функции, если вы развертываете его как приложение WSGI. Стиль «tornado
» в основном означает использование неблокирующих API для всех операций ввода-вывода и использование подпроцессов для обработки любых длительных операций с привязкой к ЦП. Документация tornado
охватывает как сделать асинхронные вызовы ввода/вывода, но вот простой пример того, как это работает:
from tornado import gen
@gen.coroutine
def fetch_coroutine(url):
http_client = AsyncHTTPClient()
response = yield http_client.fetch(url)
return response.body
response = yield http_client.fetch(curl)
вызов фактически асинхронный; он вернет управление циклу событий торнадо, когда начнется запрос, и снова возобновится после получения ответа. Это позволяет одновременно запускать несколько асинхронных HTTP-запросов, все в одном потоке.Сделайте примечание, хотя, что все, что вы делаете внутри fetch_coroutine
, что не асинхронного ввода/вывода будет блокировать цикл обработки событий, и никакие другие запросы не могут быть обработаны в то время как этот код работает.
Для решения длительных операций CPU переплета, вам необходимо отправить работу на подпроцесс, чтобы избежать блокировок цикла обработки событий. Для Python это обычно означает либо multiprocessing
, либо concurrent.futures
. Я бы посмотрел на this question для получения дополнительной информации о том, как лучше всего интегрировать эти библиотеки с tornado
. Обратите внимание, что вы не хотите поддерживать пул процессов больше, чем количество процессоров, которые у вас есть в системе, поэтому рассмотрите, сколько одновременных операций, связанных с процессором, вы планируете запускать в любой момент времени, когда вы выясняете, как масштабировать его за пределы одной машины.
Торнадо документация has a section dedicated to running behind a load balancer, а также. Они рекомендуют использовать NGINX для этой цели.
Просто добавив '@ tornado.gen.coroutine' декоратора в обработчик не делает его асинхронно. Вы также должны делать неблокирующие вызовы внутри обработчика. Если вы выполняете какие-либо операции блокировки в функции, весь цикл событий будет заблокирован, если вы используете декоратор 'coroutine' или нет. – dano
Ты прав, моя ошибка. можете ли вы использовать grequests для получения асинхронных запросов? – ragingSloth
'grequests' использует' gevent' для обеспечения асинхронного ввода-вывода, да. Если вы используете 'tornado', вы, вероятно, захотите использовать его встроенный' AsyncHTTPClient', хотя, поскольку он интегрируется с циклом событий торнадо. – dano