Сколько одновременных запросов получает один процесс Flask?

139

Я создаю приложение с помощью Flask, но я мало знаю о WSGI и его базе HTTP, Werkzeug. Когда я начинаю обслуживать приложение Flask с помощью gunicorn и 4 рабочих процессов, означает ли это, что я могу обрабатывать 4 одновременных запроса?

Я имею в виду одновременные запросы, а не запросы в секунду или что-то еще.

Carson
источник

Ответы:

184

При запуске сервера разработки - это то, что вы получаете, запустив app.run() , вы получаете один синхронный процесс, что означает, что одновременно обрабатывается не более 1 запроса.

Поместив Gunicorn перед ним в его конфигурацию по умолчанию и просто увеличив количество --workers, вы получите, по сути, количество процессов (управляемых Gunicorn), каждый из которых ведет себя как app.run()сервер разработки. 4 рабочих == 4 одновременных запроса. Это потому, что Gunicorn syncпо умолчанию использует свой включенный рабочий тип.

Важно отметить, что Gunicorn также включает асинхронные рабочие процессы, а именно eventletи gevent(а также tornado, но, кажется, лучше всего использовать его с фреймворком Tornado). Указав один из этих асинхронных рабочих --worker-classпроцессов с помощью флага, вы получите Gunicorn, управляющий несколькими асинхронными процессами, каждый из которых управляет собственным параллелизмом. Эти процессы не используют потоки, а вместо них сопрограммы. По сути, внутри каждого процесса одновременно может происходить только 1 событие (1 поток), но объекты могут быть «приостановлены», когда они ожидают завершения внешних процессов (например, запросы к базе данных или ожидание сетевого ввода-вывода).

Это означает, что если вы используете один из асинхронных воркеров Gunicorn, каждый воркер может обрабатывать гораздо больше, чем один запрос за раз. Какое количество воркеров лучше всего зависит от характера вашего приложения, его среды, оборудования, на котором оно работает, и т. Д. Более подробную информацию можно найти на странице дизайна Gunicorn, а заметки о том, как работает gevent, - на его вводной странице.

Райан Артекона
источник
4
Gunicorn теперь поддерживает "настоящие" потоки, начиная с версии 19. Посмотрите это и это .
Филипе Коррейя
2
Как отслеживать, какие ресурсы используются совместно (и как), а какие полностью разделены между потоками / процессами? Например, как бы я справился с ситуацией, когда я хочу разделить огромную структуру данных между несколькими процессами, обрабатываемыми Gunicorn и используемыми в обработчиках Flask?
Johann Petrak
То, что вы спрашиваете @Johsm, похоже на вопрос о том, как обмениваться данными между различными процессами в операционной системе. Ответ на этот вопрос может ответить на ваш вопрос: вы должны использовать внешнее хранилище, поскольку процессы не разделяют свою память с другими процессами. Gunicorn здесь только для того, чтобы использовать многопроцессорные архитектуры ЦП, но не для решения этих проблем.
adkl
А что насчет Евы? Это относится и к Еве?
Эсвар
2
сервер разработки
Flask
41

В настоящее время существует гораздо более простое решение, чем уже предоставленные. При запуске вашего приложения вам просто нужно передать threaded=Trueпараметр в app.run()вызов, например:

app.run(host="your.host", port=4321, threaded=True)

Другой вариант, который мы видим в документации werkzeug , - использовать processesпараметр, который получает число> 1, указывающее максимальное количество одновременных процессов для обработки:

  • многопоточный - должен ли процесс обрабатывать каждый запрос в отдельном потоке?
  • процессы - если больше 1, то обрабатывать каждый запрос в новом процессе до этого максимального количества одновременных процессов.

Что-то вроде:

app.run(host="your.host", port=4321, processes=3) #up to 3 processes

Дополнительная информация о run()методе здесь , а также сообщение в блоге, которое привело меня к поиску решения и ссылки на API.


Примечание: в документации Flask о run()методах указано, что использование его в производственной среде не рекомендуется, потому что ( цитата ): «Хотя встроенный сервер Flask легкий и простой в использовании, он не подходит для производства, поскольку он плохо масштабируется. «.

Тем не менее, они указывают на свою страницу параметров развертывания рекомендуемые способы сделать это при переходе на производство.

DarkCygnus
источник
5
Спасибо за информацию. Важно отметить, что в документе для запуска указано, что его не следует использовать в производственной среде, поскольку он не соответствует требованиям безопасности или производительности.
Coffee_fan
1
@Coffee_fan, ты прав. Даже в последней версии 1.1.x они не одобряют этого и вместо этого предлагают проверить свою страницу о вариантах развертывания при переходе на производство. Включая ваше ценное наблюдение в ответ :)
DarkCygnus
33

Flask будет обрабатывать по одному запросу на поток одновременно. Если у вас есть 2 процесса с 4 потоками в каждом, это 8 одновременных запросов.

Flask не создает и не управляет потоками или процессами. Это ответственность шлюза WSGI (например, gunicorn).

юлианский день.
источник
9

Нет, ты определенно справишься и с большим.

Важно помнить, что глубоко внутри, предполагая, что вы работаете на одноядерной машине, ЦП действительно выполняет только одну инструкцию * за раз.

А именно, ЦП может выполнять только очень ограниченный набор инструкций, и он не может выполнять более одной инструкции за один такт (многие инструкции даже занимают более одного такта).

Следовательно, параллелизм, о котором мы говорим в компьютерных науках, - это параллелизм программного обеспечения. Другими словами, существуют уровни программной реализации, которые абстрагируют от нас ЦП нижнего уровня и заставляют думать, что мы выполняем код одновременно.

Эти «вещи» могут быть процессами, то есть единицами кода, которые запускаются одновременно в том смысле, что каждый процесс думает, что он работает в своем собственном мире со своей собственной, не разделяемой памятью.

Другой пример - потоки, которые представляют собой блоки кода внутри процессов, которые также допускают параллелизм.

Причина, по которой ваши 4 рабочих процесса смогут обрабатывать более 4 запросов, заключается в том, что они будут запускать потоки для обработки все большего количества запросов.

Фактический лимит запросов зависит от выбранного HTTP-сервера, ввода-вывода, ОС, оборудования, сетевого подключения и т. Д.

Удачи!

* инструкции - это самые простые команды, которые может выполнять ЦП. примеры - сложить два числа, перейти от одной инструкции к другой

user1094786
источник
1
Gunicorn порождает нити или Flask? Я не нашел никаких доказательств, подтверждающих любую возможность.
jd.
1
Конечно, я понимаю это о процессах, но в ответе говорится, что при необходимости создается больше потоков. Я хотел бы получить подтверждение.
jd.
4
«в глубине души, предполагая, что вы работаете на одноядерной машине, ЦП на самом деле выполняет только одну инструкцию * за раз» Это неверно на современных машинах. Большинство современных ЦП являются конвейерными и суперскалярными , где даже одно ядро ​​имеет несколько исполнительных блоков и декодер команд, который преобразует «машинный код», видимый со стороны программного обеспечения, в фактические аппаратные микрооперации, которые отправляются отдельным исполнительным блокам.
Майкл Гири
1
Чтобы уточнить, в свое время ЦП действительно напрямую выполняли числовые инструкции в исполняемом файле - машинном коде. Каждая ссылка на ЦП имела временную диаграмму инструкций, показывающую, сколько тактов занимает каждая инструкция, включая любые обращения к памяти. Таким образом, вы можете просто сложить тайминги, чтобы узнать, сколько времени займет любой фрагмент кода. Современные процессоры совсем не такие. Одно интересное исключение - это BeagleBone, который имеет современный суперскалярный процессор ARM и два старомодных процессора PRU с фиксированной синхронизацией команд.
Майкл Гири
1
И чтобы уточнить это , когда я сказал «современный», я использовал это как вольное сокращение для процессоров, таких как чипы ARM / Intel / AMD - конвейерные, суперскалярные и т. Д. Конечно, есть также современные процессоры, которые работают по старинке с фиксированной синхронизацией. на каждую инструкцию, например PRU BeagleBone, о которых я упоминал, и различные новые микроконтроллеры. (А теперь вернемся к Gunicorn!)
Майкл Гири