2013-06-23 23 views
8

Mam wielu klientów próbujących połączyć się ze strumieniem wysyłanych zdarzeń serwera pod numerem /stream. Działa to z pojedynczym klientem, ale próba połączenia kolejnych klientów powoduje, że nowy klient staje się bezterminowo zablokowany, czekając na dane. Jeśli wyślę więcej danych, przejdzie ona tylko do pierwszego klienta, a nie do innych.Zdarzenia wysłane przez serwer za pomocą Flask/Redis: w jaki sposób więcej niż jeden klient może oglądać strumień?

Oto mały fragment, który ilustruje mój problem:

import flask 
import time 

app = flask.Flask(__name__) 

def event_stream(): 
    for i in xrange(9999): 
     yield "data: %d\n\n" % i 
     time.sleep(1) 

@app.route("/stream", methods=[ "GET" ]) 
def stream(): 
    return flask.Response(
     event_stream(), 
     mimetype="text/event-stream" 
    ) 

I następnie uruchomić ten z gunicorn --worker-class=gevent -w 4 -t 99999 app:app. Działa dla pojedynczego klienta, ale wszystkie inne są blokowane podczas wydawania GET /stream.

Jaka jest przyczyna blokady i jak ją naprawić?

I debugowałem trochę więcej i otrzymałem dziwne wyniki. Jeśli zrobię tę procedurę, to się dzieje:

  • klient start 1 (tylko klient 1 odbieranie danych)
  • klient Rozpocznij 2 (tylko klient 1 odbieranie danych)
  • start klient 3 (tylko klient 1 odbiorczy danych)
  • klient start 4 (tylko klient 1 odbieranie danych)
  • klient Restart 1 (wszystkie 4 klienci nagle zacząć odbierać dane w tym samym czasie)
+0

http://stackoverflow.com/questions/13386681/streaming-data-with-python-and-flask – farzad

+0

@farzad Ten przykład również cierpi z powodu tego problemu. –

Odpowiedz

2

Okazuje się, że ma to coś wspólnego z przeglądarką internetową Chromium, w której testowałem. Powstrzymuje się od złożenia prośby, aż do momentu, gdy pierwsza z nich zakończy się z jakiegoś powodu. Korzystanie z sesji curl lub sesji przeglądarki incognito umożliwia jednoczesne uruchamianie wielu sesji. Oznacza to, że mój problem tak naprawdę nie istnieje w rzeczywistości, po prostu wydaje się taki ze względu na sposób, w jaki Chrom obsługuje równoczesne żądania do tego samego zasobu.

Nie jestem pewien, dlaczego Chromium zachowuje się w ten sposób, wydaje się dziwne. Tak czy inaczej, nie jest to prawdziwy problem, a jedynie postrzegany przez moją przeglądarkę.

+0

Mam podobne wyniki w Firefoksie na OSX. Jeśli wykonam ten sam test z drugiej zakładki, czeka on aż pierwszy zawiesza się (po około 30 sekundach), a następnie się uruchamia. Uruchomienie okna prywatnego pozwala na jednoczesną pracę dwóch sesji. – Spaceghost

+0

Dotyczy to również Chrome 35 i Opery 22, ale nie Firefoksa 29. Wszystko w systemie Windows. – rhyek

2

Otrzymałem podobne wyniki w Firefoksie (jak zauważyłem w komentarzach), a następnie przełączyłem się na używanie WSGIServer w głównym bloku zamiast na gunicorn i wszystko działa, upłynął limit czasu (ponieważ WSGIServer nie traci czasu na swoich pracowników, ale gunicorn), więc pomyślałem, że warto to dodać jako odpowiedź.

Dodaj to:

if __name__ == '__main__': 
http_server = WSGIServer(('127.0.0.1', 8001), app) 
http_server.serve_forever() 

Następnie wystarczy zrobić

python app.py 

[I nie miałby czas, po upływie 30s gdybym użył wiersza poleceń Chris' i ustawić limit czasu do 99999, ale nie będzie znacznie później]

+0

To nie był problem w moim przypadku, ale zgadzam się, że może pojawić się w innych przypadkach. Dzięki! –

+0

Czy poza curl widzieliście tę pracę z czymkolwiek innym niż Chromium? – Spaceghost

+0

Nie, nie zrobiłem tego. Myślę, że powinno to być łatwe do odtworzenia dla każdego, kto chce zbadać dalej :-) –