2015-04-08 25 views
6

Próbuję wykonać długie polling z JQuery i Python w ramach Flask Framework.Long Polling w Pythonie z kolbą

Uczyniwszy przed długie odpytywanie w PHP, starałem się go o to w ten sam sposób:

Skrypt/funkcja, która ma while (true) pętli, sprawdzanie zmian okresowo eg.every 0 , 5 sekund w bazie danych i zwraca niektóre dane po wystąpieniu zmiany.

Tak więc w moim ini .py utworzyłem app.route do/poll dla JQuery, aby zadzwonić. JQuery podaje mu pewne informacje o bieżącym stanie klienta, a funkcja poll() porównuje to z tym, co aktualnie znajduje się w bazie danych. Pętla jest zakończona i zwraca informację, gdy zaobserwowana jest zmiana.

Oto kod Python:

@app.route('/poll') 
def poll(): 
client_state = request.args.get("state") 

    #remove html encoding + whitesapce from client state 
    html_parser = HTMLParser.HTMLParser() 
    client_state = html_parser.unescape(client_state) 
    client_state = "".join(client_state.split()) 

    #poll the database 
    while True: 
     time.sleep(0.5) 
     data = get_data() 
     json_state = to_json(data) 
     json_state = "".join(data) #remove whitespace 

     if json_state != client_state: 
      return "CHANGE" 

Problem polega na tym, że kiedy wyżej kod rozpoczyna odpytywanie, serwer wydaje się być przeładowany i inne Ajax wzywa, i inne wnioski, takie jak załadowanie „Ładowanie” obraz do HTML przy użyciu JQuery nie odpowiada i nie ma limitu czasu.

Na litość Zakończenie za podaję jQuery tutaj:

function poll() { 

queryString = "state="+JSON.stringify(currentState); 

$.ajax({ 
    url:"/poll", 
    data: queryString, 
    timeout: 60000, 
    success: function(data) { 
     console.log(data); 
     if(currentState == null) { 
      currentState = JSON.parse(data); 
     } 
     else { 
      console.log("A change has occurred"); 
     } 

     poll(); 

    }, 
    error: function(jqXHR, textStatus, errorThrown) { 

     console.log(jqXHR.status + "," + textStatus + ", " + errorThrown); 

     poll(); 

    } 
}); 

} 

Czy to potrzeba wielowątkowy czy coś? Czy ktoś może mieć jakiś pomysł, dlaczego doświadczam tego zachowania?

Z góry dziękuję !! :)

+5

Zobacz http://stackoverflow.com/questions/14814201/can-i-serve-multiple-clients-using-just-flask-app-run-as-standalone –

Odpowiedz

3

Tak jak wspomniano o link @ Robᵩ, aplikacja do kolb jest po prostu przeciążona. Dzieje się tak dlatego, że aplikacja do kolb jest domyślnie w trybie pojedynczego wątku podczas pracy z app.run(), więc może wysyłać tylko jedną prośbę za każdym razem.

można uruchomić z wielu wątków:

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

Albo za pomocą serwera WSGI jak gunicorn lub uwsgi służyć kolby z multi przetwarzania:

gunicorn -w 4 myapp:app 

Hopes jesteś korzystających z Python i kolby !

+1

Na ogół jednak aplikacje WSGI nie nadają się na długie sondowanie w dowolnej skali, chociaż to samo dotyczy również PHP. Dzieje się tak dlatego, że zarówno Python podczas korzystania z WSGI i PHP są systemami synchronicznymi i potrzebują procesu lub wątku do obsługi każdego żądania. W związku z tym, aby obsłużyć dużą liczbę równoczesnych długich żądań odpytywania, potrzebna jest duża pojemność (procesy lub wątki). Długie odpytywanie jest lepiej zaimplementowane za pomocą asynchronicznego serwera WWW i frameworka. –

+0

Alternatywą, jeśli używasz gunicorn jest używanie coroutines przez eventlet lub geven workers. Jednakże, pomimo tego, nakłada on wiele ograniczeń na twoją aplikację, ponieważ możesz używać klientów tylko do obsługi backendu i baz danych, które są zgodne z oczekiwaniami, aby uniknąć blokowania całego procesu. Coroutines nie są po prostu magią, która czyni wszystko dobrze. –

+0

@GrahamDumpleton Tak, serwer asynchroniczny chciałby, aby Tornado było znacznie lepsze i zazwyczaj jest to mój pierwszy wybór do budowy API lub serwera WebSocket. – kxxoling