Ile równoczesnych żądań otrzymuje pojedynczy proces Flask?

143

Tworzę aplikację za pomocą Flaska, ale nie wiem zbyt wiele o WSGI i jest to baza HTTP, Werkzeug. Kiedy zaczynam obsługiwać aplikację Flask z gunicorn i 4 procesami roboczymi, czy to oznacza, że ​​mogę obsłużyć 4 jednoczesne żądania?

Mam na myśli jednoczesne żądania, a nie żądania na sekundę lub cokolwiek innego.

Carson
źródło

Odpowiedzi:

191

Podczas uruchamiania serwera deweloperskiego - co uzyskujesz uruchamiając app.run(), uzyskujesz pojedynczy proces synchroniczny, co oznacza, że ​​maksymalnie 1 żądanie jest przetwarzane na raz.

Trzymając Gunicorn przed nim w jego domyślnej konfiguracji i po prostu zwiększając liczbę --workers, otrzymujesz zasadniczo liczbę procesów (zarządzanych przez Gunicorn), z których każdy zachowuje się jak app.run()serwer deweloperski. 4 pracowników == 4 jednoczesne żądania. Dzieje się tak, ponieważ Gunicorn domyślnie używa dołączonego synctypu pracownika.

Ważne jest, aby zauważyć, że Gunicorn obejmuje również pracowników asynchronicznych, a mianowicie eventleti gevent(a także tornado, ale wydaje się, że najlepiej jest to używać z frameworkiem Tornado). Określając jednego z tych pracowników asynchronicznych za pomocą --worker-classflagi, otrzymujesz Gunicorn zarządzający wieloma procesami asynchronicznymi, z których każdy zarządza własną współbieżnością. W tych procesach nie są używane wątki, ale programy. Zasadniczo w każdym procesie może się zdarzyć tylko 1 rzecz naraz (1 wątek), ale obiekty można „wstrzymać”, gdy oczekują na zakończenie procesów zewnętrznych (pomyśl o zapytaniach do bazy danych lub oczekiwaniu na operacje we / wy sieci).

Oznacza to, że jeśli używasz jednego z pracowników asynchronicznych Gunicorn, każdy pracownik może obsłużyć więcej niż jedno żądanie na raz. To, ilu pracowników jest najlepsze, zależy od charakteru aplikacji, jej środowiska, sprzętu, na którym działa, itp. Więcej szczegółów można znaleźć na stronie projektu Gunicorn i uwagach na temat działania gevent na stronie wprowadzającej.

Ryan Artecona
źródło
4
Gunicorn obsługuje teraz "prawdziwe" wątki od wersji 19. Zobacz to i to .
Filipe Correia
2
W jaki sposób można śledzić, które zasoby są udostępniane (i jak), a które są całkowicie oddzielone między wątkami / procesami? Na przykład, jak poradziłbym sobie z sytuacją, w której chciałbym współdzielić ogromną strukturę danych między kilkoma procesami obsługiwanymi przez Gunicorn i używanymi w programach obsługi kolb?
jpp1
To, o co prosisz @Johsm, przypomina pytanie, jak udostępniać dane między różnymi procesami w systemie operacyjnym. Odpowiedź na to może odpowiedzieć na twoje pytanie, musisz korzystać z pamięci zewnętrznej, ponieważ procesy nie współdzielą swojej pamięci z innymi procesami. Gunicorn jest tutaj tylko po to, aby wykorzystywać architekturę wieloprocesorowych procesorów, ale nie rozwiązuje tych problemów.
adkl
A co z Ewą? Czy to dotyczy również Ewy?
Eswar
2
serwer programistyczny flask domyślnie używa wątków od wersji 1.0 ( github.com/pallets/flask/pull/2529 )
hychou
43

Obecnie istnieje dużo prostsze rozwiązanie niż te już dostarczone. Podczas uruchamiania aplikacji wystarczy przekazać threaded=Trueparametr do app.run()wywołania, na przykład:

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

Inną opcją, zgodnie z tym, co widzimy w dokumentach werkzeug , jest użycie processesparametru, który otrzymuje liczbę> 1 wskazującą maksymalną liczbę współbieżnych procesów do obsłużenia:

  • wątkowe - czy proces powinien obsługiwać każde żądanie w osobnym wątku?
  • procesy - jeśli jest większe niż 1, obsługuje każde żądanie w nowym procesie aż do maksymalnej liczby współbieżnych procesów.

Coś jak:

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

Więcej informacji na temat run()metody można znaleźć tutaj , oraz w poście na blogu, który doprowadził mnie do znalezienia rozwiązania i odniesień do interfejsu API.


Uwaga: w dokumentacji Flask na temat run()metod wskazano, że używanie go w środowisku produkcyjnym jest odradzane, ponieważ ( cytat ): „Chociaż jest lekki i łatwy w użyciu, wbudowany serwer Flask nie nadaje się do produkcji, ponieważ nie skaluje się dobrze ”.

Wskazują jednak na stronę Opcje wdrażania, aby zapoznać się z zalecanymi sposobami zrobienia tego podczas przechodzenia do produkcji.

DarkCygnus
źródło
5
Dzięki za informację. Należy zauważyć, że dokumentacja dotycząca uruchamiania stwierdza, że ​​nie powinna być używana w środowisku produkcyjnym, stwierdzając, że nie spełnia ona wymagań dotyczących bezpieczeństwa lub wydajności.
Coffee_fan
1
@Coffee_fan masz rację. Nawet w najnowszej wersji 1.1.x odradzają to i zamiast tego sugerują, aby przed przejściem do produkcji sprawdzić swoją stronę dotyczącą opcji wdrażania . Włączając cenną obserwację do odpowiedzi :)
DarkCygnus
33

Flask będzie przetwarzać jedno żądanie na wątek w tym samym czasie. Jeśli masz 2 procesy, każdy z 4 wątkami, oznacza to 8 jednoczesnych żądań.

Flask nie uruchamia się ani nie zarządza wątkami ani procesami. To jest odpowiedzialność bramy WSGI (np. Gunicorn).

jd.
źródło
9

Nie - zdecydowanie poradzisz sobie z czymś więcej.

Ważne jest, aby pamiętać, że w głębi duszy, zakładając, że używasz maszyny z jednym rdzeniem, procesor tak naprawdę wykonuje tylko jedną instrukcję * na raz.

Mianowicie, procesor może wykonać tylko bardzo ograniczony zestaw instrukcji i nie może wykonać więcej niż jednej instrukcji na takt zegara (wiele instrukcji zajmuje nawet więcej niż 1 takt).

Dlatego większość współbieżności, o której mówimy w informatyce, to współbieżność oprogramowania. Innymi słowy, istnieją warstwy implementacji oprogramowania, które odejmują od nas procesor najniższego poziomu i sprawiają, że myślimy, że jednocześnie wykonujemy kod.

Te „rzeczy” mogą być procesami, które są jednostkami kodu uruchamianymi jednocześnie w tym sensie, że każdy proces myśli, że działa w swoim własnym świecie z własną, niewspółdzieloną pamięcią.

Innym przykładem są wątki, które są jednostkami kodu wewnątrz procesów, które również umożliwiają współbieżność.

Powodem, dla którego 4 procesy robocze będą w stanie obsłużyć więcej niż 4 żądania, jest to, że będą odpalać wątki, aby obsłużyć coraz więcej żądań.

Rzeczywisty limit żądań zależy od wybranego serwera HTTP, I / O, systemu operacyjnego, sprzętu, połączenia sieciowego itp.

Powodzenia!

* instrukcje to bardzo podstawowe polecenia, które może wykonać procesor. przykłady - dodaj dwie liczby, przeskocz z jednej instrukcji do drugiej

user1094786
źródło
1
Czy to Gunicorn spawnujący nici czy Flask? Nie znalazłem żadnych dowodów na poparcie którejkolwiek możliwości.
jd.
1
Jasne, rozumiem to o procesach, ale odpowiedź mówi, że w razie potrzeby powstaje więcej wątków. Właśnie tego chciałbym mieć potwierdzenie.
jd.
4
„W głębi duszy, zakładając, że używasz maszyny jednordzeniowej, procesor tak naprawdę wykonuje tylko jedną instrukcję * na raz”. Nie jest to poprawne na nowoczesnych maszynach. Większość nowoczesnych procesorów jest potokowych i superskalarnych , gdzie nawet pojedynczy rdzeń ma wiele jednostek wykonawczych i dekoder instrukcji, który konwertuje „kod maszynowy” widziany od strony oprogramowania na rzeczywiste mikrooperacje sprzętowe, które są wysyłane do poszczególnych jednostek wykonawczych.
Michael Geary,
1
Aby wyjaśnić, w dawnych czasach procesory faktycznie wykonywały instrukcje numeryczne bezpośrednio w pliku wykonywalnym - kodzie maszynowym. Każde odniesienie CPU miało wykres czasowy instrukcji pokazujący, ile cykli zegara zajęła każda instrukcja, w tym odwołania do pamięci. Możesz więc po prostu dodać czasy, aby wiedzieć, ile czasu zajmie dowolny fragment kodu. Nowoczesne procesory wcale takie nie są. Interesującym wyjątkiem jest BeagleBone, który ma nowoczesny superskalarny procesor ARM i dwa staromodne procesory „PRU” ze stałym taktowaniem instrukcji.
Michael Geary,
1
I wyjaśnić, że , kiedy powiedziałem „nowoczesny” używałem go jako luźny skrót dla procesorów ARM, takich jak chipsy / Intel / AMD - potokowym, Superskalarna, itd. Oczywiście są też nowoczesne procesory, które działają po staremu ze stałą czasu zgodnie z instrukcją, jak wspomniane przeze mnie PRU BeagleBone i różne nowe mikrokontrolery. (A teraz wracając do Gunicorn!)
Michael Geary,