Czy mogę obsługiwać wielu klientów, używając tylko Flask app.run () jako samodzielnej wersji?

201

Wiem, że mogę połączyć Flask z Apache lub innymi serwerami WWW. Ale myślałem o uruchomieniu Flask jako samodzielnego serwera obsługującego wielu klientów jednocześnie.

czy to możliwe? Czy muszę obsługiwać spawnowanie wielu wątków i zarządzanie nimi?

ATOzTOA
źródło

Odpowiedzi:

295

flask.Flask.runakceptuje dodatkowe argumenty słów kluczowych ( **options), które przekazuje werkzeug.serving.run_simple- dwa z tych argumentów to threaded(logiczne) i processes(które można ustawić na liczbę większą niż jeden, aby werkzeug spawnował więcej niż jeden proces do obsługi żądań).

threadeddomyślnie na Truepoziomie Flask 1.0, więc w najnowszych wersjach Flask domyślny serwer programistyczny będzie mógł domyślnie obsługiwać wielu klientów jednocześnie. W przypadku starszych wersji Flask możesz jawnie przejść, threaded=Trueaby włączyć to zachowanie.

Na przykład możesz to zrobić

if __name__ == '__main__':
    app.run(threaded=True)

do obsługi wielu klientów używających wątków w sposób zgodny ze starymi wersjami Flask, lub

if __name__ == '__main__':
    app.run(threaded=False, processes=3)

aby powiedzieć Werkzeugowi, aby stworzył trzy procesy do obsługi przychodzących żądań lub po prostu

if __name__ == '__main__':
    app.run()

do obsługi wielu klientów używających wątków, jeśli wiesz, że będziesz używać Flask 1.0 lub nowszej wersji.

To powiedziawszy, Werkzeug's serving.run_simpleotacza standardowy wsgirefpakiet biblioteki - i ten pakiet zawiera referencyjną implementację WSGI, a nie gotowy do produkcji serwer WWW. Jeśli zamierzasz używać Flask w środowisku produkcyjnym (zakładając, że „produkcja” nie jest aplikacją wewnętrzną o niskim natężeniu ruchu, z nie więcej niż 10 równoczesnymi użytkownikami), upewnij się, że stoi on za prawdziwym serwerem internetowym (zobacz sekcję dokumentacji Flask zatytułowaną Opcje wdrażania dla niektórych sugerowanych metod).

Sean Vieira
źródło
2
Co jeśli patrzę na maksymalnie 100 użytkowników? Czy mogę to przypisać processes=100i być z tego zadowolonym? W moim przypadku potrzebuję tylko plików statycznych, bez metod HTTP Post. Moje wymaganie polega na tym, że chcę uruchamiać wszystkie wątki Flask jako część mojej aplikacji nadrzędnej, aby wszystkie mogły współdzielić zmienne.
ATOzTOA,
4
Chichocze - @ATOzTOA - Nie, to prawdopodobnie byłby zupełnie nieproduktywne (Procesy są stosunkowo drogie i jeśli robisz dużo pracy w każdym żądaniu nie ma powodu, dlaczego 4 lub 8 procesy nie powinno wystarczyć). To powiedziawszy, jeśli wyświetlasz tylko zawartość statyczną, lepiej byłoby, gdyby serwer był zoptymalizowany do tego (Apache, ngnix, IIS).
Sean Vieira,
2
Ponadto, zwykle nie powinieneś współdzielić zmiennych między żądaniami - jeśli to zrobisz , musisz ograniczyć się do jednego procesu lub skorzystać z komunikacji pozapasmowej (Redis, baza danych, system plików itp.), Więc że każdy proces pozostaje zsynchronizowany.
Sean Vieira,
3
@ATOzTOA - jeśli nie możesz podkręcić lepszego serwera, to po prostu dałbym mu wir i zobaczyłbym, co się stanie. Jeśli nie działa dobrze pod obciążeniem, możesz wdrożyć go za innym serwerem WWW.
Sean Vieira,
2
@ATOzTOA, jeśli chodzi o pytanie, dlaczego nie można jednocześnie określić „wątków” i „procesów”, patrz poniższy kod: werkzeug.readthedocs.org/en/latest/_modules/werkzeug/serving
pyrho
62

Korzystanie z prostego app.run()z poziomu Flask tworzy pojedynczy serwer synchroniczny w jednym wątku, który może obsługiwać tylko jednego klienta na raz. Jest przeznaczony do użytku w kontrolowanych środowiskach o niskim zapotrzebowaniu (tj. Programowanie, debugowanie) właśnie z tego powodu.

Odnawianie wątków i samodzielne zarządzanie nimi prawdopodobnie nie doprowadzi cię zbyt daleko, ze względu na Python GIL .

To powiedziawszy, wciąż masz kilka dobrych opcji. Gunicorn to solidny, łatwy w użyciu serwer WSGI, który pozwoli Ci spawnować wielu pracowników (osobne procesy, więc nie martw się GIL), a nawet zawiera asynchronicznych pracowników, którzy przyspieszą twoją aplikację (i zwiększą jej bezpieczeństwo) przy niewielkim nie pracować z twojej strony (szczególnie z Flask).

Mimo to nawet Gunicorn prawdopodobnie nie powinien być bezpośrednio upubliczniony. W produkcji powinien być używany za bardziej niezawodnym serwerem HTTP; nginx zwykle dobrze komponuje się z Gunicorn i Flask.

Ryan Artecona
źródło
17
nie do końca. Gunicorn to python, nginx nie. nie tak byś ich używał. Gunicorn pozwoli Ci uruchomić aplikację tak jak gunicorn app:app 127.0.0.1:8080zamiast python app.py. Nginx działałby jako usługa publiczna, która ujawnia twoją prywatną aplikację uruchomioną przez Gunicorn (odwrotny serwer proxy) , ukrywając wszelkiego rodzaju szczegóły implementacji HTTP niższego poziomu, być może bezpośrednio obsługując pliki statyczne itp.
Ryan Artecona
Flask z app.run (threaded = True) działa bardzo dobrze na Apache2 przy użyciu mod_wsgi flask.palletsprojects.com/en/1.1.x/deploying/mod_wsgi
MortenB