2016-01-11 53 views
8

Próbuję skonfigurować minimalną aplikację Flask, która używa eventlet, aby natychmiastowo odpowiadać na żądania równoczesne zamiast blokować i odpowiadać na jedno żądanie po drugim (tak jak robi to standardowy serwer debugowania Flas).Odpowiadanie na równoczesne żądania za pomocą kolby i zdarzenia

Wymagania:

pip install Flask 
pip install eventlet 

Z mojego zrozumienia przez co znalazłem do tej pory w internecie, to powinno działać tak:

# activate eventlet 
import eventlet 
eventlet.monkey_patch() 

from flask import Flask 

import datetime 
from time import sleep 

# create a new Flask application 
app = Flask(__name__) 

# a short running task that returns immediately 
@app.route('/shortTask') 
def short_running_task(): 
    start = datetime.datetime.now() 
    return 'Started at {0}, returned at {1}'.format(start, datetime.datetime.now()) 

# a long running tasks that returns after 30s 
@app.route('/longTask') 
def long_running_task(): 
    start = datetime.datetime.now() 
    sleep(30) 
    return 'Started at {0}, returned at {1}'.format(start, datetime.datetime.now()) 

# run the webserver 
if __name__ == '__main__': 
    app.run(debug=True) 

Po uruchomieniu tego pliku, a następnie otwierając http://localhost:5000/longTask w WebBrowser i gdy nadal przetwarza otwierając kolejną zakładkę z http://localhost:5000/shortTask, oczekiwałbym, że druga karta natychmiast powróci, podczas gdy pierwsza karta będzie nadal ładowana. Jednak, podobnie jak przy uruchamianiu tego na standardowym serwerze Werkzeug, druga karta zwraca się zaraz po zakończeniu pierwszej po 30 sekundach.

Co jest nie tak? A tak przy okazji, czy to by było powszechnie nazywane "produkcyjnym serwerem internetowym" dla Flask, biorąc pod uwagę, że można oczekiwać tylko kilku jednoczesnych użytkowników (maksymalnie 5)?

Nawiasem mówiąc, kiedy używam the Flask-socketio library do uruchamiania serwera sieciowego, który zgodnie z dokumentacją automatycznie wybiera zdarzenie, jeśli jest zainstalowany, działa zgodnie z oczekiwaniami.

Kompletny przykład z kolbą-socketio:

# activate eventlet 
import eventlet 
eventlet.monkey_patch() 

from flask import Flask 
from flask_socketio import SocketIO 

import datetime 
from time import sleep 

# create a new Flask application 
app = Flask(__name__) 

# activate Flask-socketio 
socketio = SocketIO(app) 

# a short running task that returns immediately 
@app.route('/shortTask') 
def short_running_task(): 
    start = datetime.datetime.now() 
    return 'Started at {0}, returned at {1}'.format(start, datetime.datetime.now()) 

# a long running tasks that returns after 30s 
@app.route('/longTask') 
def long_running_task(): 
    start = datetime.datetime.now() 
    sleep(30) 
    return 'Started at {0}, returned at {1}'.format(start, datetime.datetime.now()) 

# run the webserver with socketio 
if __name__ == '__main__': 
    socketio.run(app, debug=True) 

Odpowiedz

11

Po uruchomieniu app.run(debug=True) wyraźnie informujesz Flask o uruchomieniu aplikacji na serwerze WWW dla programistów, który jest oparty na Werkzeug. Nie ma znaczenia, że ​​załadowałeś wydarzenie.

Jeśli chcesz uruchomić aplikację na serwerze eventlet internetowej, trzeba uruchomić serwer WWW eventlet, który według the documentation uruchomieniu następująco:

wsgi.server(eventlet.listen(('', 8000)), your_app) 

To jest mniej więcej to, co socketio.run() robi w moim rozszerzeniu Flask-SocketIO, z nieco większą złożonością, aby opcjonalnie obsługiwać SSL. Linie kodu, które to robią to: https://github.com/miguelgrinberg/Flask-SocketIO/blob/539cd158f49ce085151911cb63edbacd0fa37173/flask_socketio/init.py#L391-L408. Jeśli rozejrzesz się po tych liniach, zobaczysz, że istnieją trzy różne początkowe fragmenty kodu, jeden dla werkzeug, jeden dla zdarzenia i jeden dla geventu. Wszystkie są różne.

+0

Doskonale! Przekazanie obiektu aplikacji Flask do polecenia wsgi.server nie było dla mnie jasne z przykładu w dokumentach zdarzeń, więc ten przykład oparty na Flask był bardzo pomocny. – Dirk

2
import eventlet 
eventlet.monkey_patch() 

nie będzie magicznie włączyć kod do wielowątkowego zwierzęcia, które może obsłużyć żądania asynchronicznie (jest jeszcze całkiem magiczne i niesamowite).

Jak widać w this example, należy uruchomić serwer wsgi przy użyciu eventlet wsgi's implementation.

Jeśli chcesz standardowego rozwiązania, zobacz, jak używać nginx i uwsgi do uruchamiania aplikacji kolby. Być może zainteresuje Cię również projekt Spawning, który pozwala uniknąć problemów związanych z tworzeniem kompletnego programu obsługi wątków wsith.