Wolne żądania na lokalnym serwerze Flask

87

Właśnie zaczynam bawić się Flaskiem na lokalnym serwerze i zauważam, że czasy żądań / odpowiedzi są znacznie wolniejsze, niż sądzę, że powinny.

Tylko prosty serwer, taki jak poniższy, potrzebuje około 5 sekund na odpowiedź.

from flask import Flask

app = Flask(__name__)

@app.route("/")
def index():
    return "index"

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

Jakieś pomysły? A może tak właśnie jest na serwerze lokalnym?

Meroon
źródło
To nie jest serwer lokalny, ale może mieć to związek z innymi aplikacjami działającymi w tle, na jakim systemie operacyjnym to działa?
gabeio
Używam OS X 10.7 na i7 iMac
Meroon
1
Twoje odpowiedzi nie powinny zająć tyle czasu, ale wcześniej bawiłem się kolbą, ale bez powodzenia radziłbym Bottlepy'emu . Chociaż nadal sprawdzaj procesy w tle, możesz mieć starszą wersję serwera działającą w tle, przejmującą język Python i powodującą powolne odpowiedzi. Może to być również Twoja przeglądarka. Czy to się dzieje w Chrome i Safari?
Gabeio
2
Odpowiedź @ Meroon była dla mnie poprawna. Zamiast jednak zmieniać ustawienia hosta: czy mogę polecić po prostu użycie 127.0.0.1 zamiast localhost? To rozwiązało problem bez zmiany konfiguracji systemu.
David Bernat,

Odpowiedzi:

94

Ok, wymyśliłem to. Wygląda na to, że jest to problem z Werkzeug i systemami operacyjnymi obsługującymi ipv6.

Z witryny Werkzeug http://werkzeug.pocoo.org/docs/serving/ :

W systemach operacyjnych, które obsługują protokół ipv6 i mają go skonfigurowane, takich jak nowoczesne systemy Linux, OS X 10.4 lub nowszy, a także Windows Vista, niektóre przeglądarki mogą działać bardzo wolno, jeśli uzyskują dostęp do lokalnego serwera. Powodem tego jest to, że czasami „localhost” jest skonfigurowany tak, aby był dostępny zarówno w gniazdach ipv4, jak i ipv6, a niektóre przeglądarki próbują najpierw uzyskać dostęp do ipv6, a następnie ivp4.

Tak więc rozwiązaniem jest wyłączenie ipv6 z lokalnego hosta przez zakomentowanie następującego wiersza z mojego pliku hosts:

::1             localhost 

Kiedy to zrobię, problemy z opóźnieniem znikną.

Naprawdę kopie Flask i cieszę się, że nie ma problemu z frameworkiem. Wiedziałem, że to niemożliwe.

Meroon
źródło
wielkie dzięki! nagle testy deweloperskie są szybkie i responsywne! moje jedyne pytanie: ponieważ plik hostów Maca wskazuje, że usunięcie localhost może wpłynąć na działanie mojego komputera Mac, zastanawiam się, czy odnosi się do tej linii (czy do tej, która po prostu lokalizuje localhost na 127.0.0.1
David B.
w moim systemie Windows 10 w pliku hosts oba wpisy (ip4 i ip6) są zakomentowane; są rozwiązywane przez system DNS. Szybkość wzrosła znacznie, gdy uruchomiłem serwer na „127.0.0.1” zamiast „localhost” (od 2,0 do 0,003 sekundy dla prostych połączeń)
Lars
Dziękuję za tę odpowiedź! Chociaż moja sytuacja była nieco inna (katar 2 w porównaniu z aiosmtpd), twoja odpowiedź dała mi wskazówkę: Kiedy wyłączam IPv6 na moim laptopie z Windows 10, przyspiesza to 10x lub 100x !!
pepoluan
91

Dodaj „threaded = True” jako argument do app.run (), jak zasugerowano tutaj: http://arusahni.net/blog/2013/10/flask-multithreading.html

Na przykład: app.run(host="0.0.0.0", port=8080, threaded=True)

Rozwiązanie wyłączające ipv6 nie działało dla mnie, ale tak się stało.

Sajid Siddiqi
źródło
5
Przejście --threadeddo mojego manage.pyużycia Flask-Scriptteż zadziałało.
Snorfalorpagus
7
Ostrzegamy, że dla tych, którzy „naprawili” to poprzez włączenie wątków! W tym przypadku opóźnienie było spowodowane nieprawidłowym zamknięciem poprzedniego żądania, więc teraz w rzeczywistości jest to po prostu układanie wielu wątków .
kbtz
1
Dziękuję panu za sprawienie, że mój lokalny serwer działa niesamowicie szybko.
benjaminz
@snolflake: Czy istnieje sposób, aby dowiedzieć się, czy żądania nie są prawidłowo zamykane?
Kylotan
1
Z wiersza poleceń użyłem, flask run --with-threadsco rozwiązało mój problem.
arno_v
13

Rozwiązanie z @ sajid-siddiqi jest technicznie poprawne, ale należy pamiętać, że wbudowany serwer WSGI w Werkzeug (który jest spakowany do Flaska i do czego służy app.run()) jest tylko jednowątkowy.

Zainstaluj serwer WSGI , aby móc obsługiwać zachowanie wielowątkowe. Zrobiłem wiele badań na temat wydajności różnych serwerów WSGI . Twoje potrzeby mogą się różnić, ale jeśli wszystko, czego używasz, to Flask , polecam jeden z poniższych serwerów internetowych.

Aktualizacja (2020-07-25): Wygląda na to, że gevent zaczął obsługiwać python3 5 lat temu, wkrótce po tym, jak skomentowałem, że tak się nie stało, więc możesz teraz używać gevent .

gevent

Możesz zainstalować gevent przez pip za pomocą polecenia pip install geventlub pip3 za pomocą polecenia pip3 install gevent. Instrukcje dotyczące odpowiedniego modyfikowania kodu znajdują się tutaj: https://flask.palletsprojects.com/en/1.1.x/deploying/wsgi-standalone/#gevent

meinheld

gevent jest lepszy, ale ze wszystkich testów porównawczych, które obejrzałem, obejmujących testy w świecie rzeczywistym, meinheld wydaje się być najprostszym i najprostszym serwerem WSGI . (Możesz również rzucić okiem na uWSGI, jeśli nie masz nic przeciwko dalszej konfiguracji.)

Możesz także zainstalować meinheld przez pip3 za pomocą polecenia pip3 install meinheld. Następnie spójrz na próbkę dostarczoną w meinheld source, aby zintegrować Flask : https://github.com/mopemope/meinheld/blob/master/example/flask_sample.py

* UWAGA: Po moim użyciu PyCharm linia jest from meinheld import serverpodświetlana jako błąd, ale serwer będzie działał, więc możesz zignorować błąd.

mikeho
źródło
Miałem poważne problemy z wydajnością z Flaskiem, nawet najprostsze żądania zajmowały około 0,5 sekundy. Właśnie przełączyłem się na gevent i wszystko działa bez zarzutu, dziękuję!
gronostaj
7

Zamiast dzwonić http://localhost:port/endpointzadzwoń http://127.0.0.1:port/endpoint. To usunęło dla mnie początkowe opóźnienie 500 ms.

LangeTreeDorpie
źródło
dla mnie usunęło to około 3 sekund (przeniosłem się z 0.0.0.0 do 127.0.0.1). Czy ktoś może wyjaśnić, dlaczego i jak to działa?
Rotkiv
Dlaczego, na Boga, to działa? Zmienił się z 2,06 sekundy do 0,002 sekundy. Przeglądarka może bez problemu korzystać z hosta lokalnego, ale rozwiązanie request.get na hoście lokalnym zajmuje 2 sekundy.
Xevion
7

Mój problem został rozwiązany przez „threaded = True”, ale chcę podać pewne tło, aby odróżnić mój problem od innych, w przypadku których może to nie wystarczyć.

  1. Mój problem pojawił się tylko podczas uruchamiania Flaska z pythonem3. Przechodząc na python2, nie miałem już tego problemu.
  2. Mój problem objawiał się tylko podczas uzyskiwania dostępu do interfejsu API za pomocą Chrome, w którym to momencie Chrome wyświetlał oczekiwany ekran, ale wszystko inne zawiesiło się (curl, ffx itp.), Dopóki nie załadowałem ponownie lub nie zamknąłem karty Chrome, w którym to momencie wszystko inne, co czekało około zwrócił wynik.

Domyślam się, że Chrome próbował utrzymać sesję otwartą, a Flask blokował kolejne żądania. Gdy tylko połączenie z Chrome zostało zatrzymane lub zresetowane, wszystko inne zostało przetworzone.

W moim przypadku gwintowanie naprawiło to. Oczywiście przeglądam teraz niektóre linki udostępnione przez innych, aby upewnić się, że nie spowoduje to żadnych innych problemów.

ChePazzo
źródło
4

threaded=Truedziała dla mnie, ale w końcu zorientowałem się, że problem jest spowodowany przez Foxyproxy w Firefoksie. Od kiedy aplikacja flask działa na hoście lokalnym, powolna odpowiedź ma miejsce, jeśli

  • foxyproxy jest włączony w przeglądarce Firefox

powolna odpowiedź nie nastąpi, jeśli

  • foxyproxy jest wyłączone w przeglądarce Firefox

  • uzyskać dostęp do witryny za pomocą innych przeglądarek

Jedynym rozwiązaniem, które znalazłem, jest wyłączenie foxyproxy, próba dodania lokalnego hosta do czarnej listy proxy i zmiana ustawień, ale żadne z nich nie działało.

Edward
źródło
2

Wykorzystałem odpowiedź Miheko, aby rozwiązać mój problem.

::1 localhostzostał już zakomentowany w moim pliku hosts, a ustawienie Threaded=truenie działa dla mnie. Każde żądanie REST trwało 1 sekundę, zamiast być natychmiastowe.

Używam Pythona 3.6 i otrzymałem flask, aby był szybki i reagował na żądania REST, dzięki czemu flask use gevent jako jego WSGI.

Aby użyć gevent, zainstaluj go z pip install gevent

Następnie użyłem https://gist.github.com/viksit/b6733fe1afdf5bb84a40#file-async_flask-py-L41, aby ustawić kolbę na używanie gevent.

O ile łącze znika, oto ważne części skryptu:

from flask import Flask, Response
from gevent.pywsgi import WSGIServer
from gevent import monkey

# need to patch sockets to make requests async
# you may also need to call this before importing other packages that setup ssl
monkey.patch_all()

app = Flask(__name__) 


# define some REST endpoints... 

def main():

    # use gevent WSGI server instead of the Flask
    # instead of 5000, you can define whatever port you want.
    http = WSGIServer(('', 5000), app.wsgi_app) 

    # Serve your application
    http.serve_forever()


if __name__ == '__main__':
    main()
Jakiś facet
źródło
threaded = True nie działa dla (używając Pythona 3.6.7 i listonosza), otrzymuję VersionConflict: (greenlet 0.4.13 (c: \ anaconda3 \ lib \ site-packages), Requirement.parse ('greenlet> = 0.4. 14; platform_python_implementation == "CPython" ')), czy mogę wiedzieć, jak to rozwiązać. Dzięki
hanzgs
0

Wystąpił ten błąd podczas uruchamiania na innych hostach niż localhostrównież, więc w przypadku niektórych różnych podstawowych problemów mogą wykazywać te same objawy.

Przerzuciłem większość rzeczy, których używałem, na Tornado i, jak anegdotycznie, pomogło mi to. Miałem kilka powolnych ładowań strony, ale generalnie rzeczy wydają się bardziej responsywne. Również bardzo anegdotyczne, ale wydaje mi się, że sam Flask zwalnia z czasem, ale Flask + Tornado mniej. Wyobrażam sobie, że używam Apache i mod_wsgisprawiłbym, że wszystko byłoby jeszcze lepsze, ale Tornado jest naprawdę proste w konfiguracji (patrz http://flask.pocoo.org/docs/deploying/others/ ).

(Również powiązane pytanie: aplikacja Flask czasami się zawiesza )

gatoatigrado
źródło
0

Miałem tutaj inne rozwiązanie. Właśnie usunąłem wszystko .pycz katalogu serwera i uruchomiłem go ponownie. Nawiasem mówiąc, localhost został już zakomentowany w moim pliku hosts (Windows 8).

Serwer przez cały czas się zamrażał i teraz znowu działa dobrze.

erickrf
źródło