2012-09-01 22 views
37

Flask 마이크로 웹 프레임 워크에서 서버 푸시 기능이있는 작은 사이트를 만들려고하지만 직접 작동하는 프레임 워크가 있는지 몰랐습니다.플라스크 프레임 워크에서 서버 푸시를 구현하는 방법은 무엇입니까?

나는 Juggernaut을 사용했지만 현재 버전에서는 redis-py과 작동하지 않는 것으로 보입니다. 그리고 Juggernaut는 최근에 사용되지 않습니다.

내 케이스에 대한 제안이있는 사람이 있습니까?

+6

[다음은 Flask의 수석 개발자 Armin Ronacher가 작성한 관련 기사입니다.] (http://lucumr.pocoo.org/2012/8/5/stateless-and-proud/) – dumbmatter

+0

related : [Streaming 데이터와 파이썬과 플라스크] (http://stackoverflow.com/q/13386681/4279) – jfs

답변

75

Server-Sent Events을 살펴보십시오. Server-Sent Events는 브라우저 스트림으로 업데이트 스트림에 가입하여 서버 소켓을 열어 둘 수 있습니다. 더 많은 정보는 Alex MacCaw (저자 : Juggernaut)의 게시물을 why he kills juggernaut에 게시하고 서버 - 보낸 이벤트가 더 나은 도구 인 경우 웹 소켓보다 더 좋은 도구라고 읽습니다.

프로토콜이 정말 쉽습니다. 응답 에 mimetype text/event-stream을 추가하기 만하면됩니다. 브라우저는 연결을 열린 상태로 유지하고 업데이트를 수신 대기합니다. 서버에서 보낸 이벤트는 data:으로 시작하는 텍스트 줄과 다음 줄 바꿈입니다.

data: this is a simple message 
<blank line> 

구조화 된 데이터를 교환하려면 데이터를 json으로 덤프하고 json을 와이어로 보냅니다.

서버가 없어도 Flask에서 SSE를 사용할 수 있다는 장점이 있습니다. 은 pub/sub 백엔드로 redis를 사용하는 github에 간단한 chat application example이 있습니다.

def event_stream(): 
    pubsub = red.pubsub() 
    pubsub.subscribe('chat') 
    for message in pubsub.listen(): 
     print message 
     yield 'data: %s\n\n' % message['data'] 


@app.route('/post', methods=['POST']) 
def post(): 
    message = flask.request.form['message'] 
    user = flask.session.get('user', 'anonymous') 
    now = datetime.datetime.now().replace(microsecond=0).time() 
    red.publish('chat', u'[%s] %s: %s' % (now.isoformat(), user, message)) 


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

당신은 예제 응용 프로그램을 실행하는 gunicron를 사용할 필요가 없습니다. 때 새 메시지 호출됩니다 그냥 자바 스크립트 핸들러 함수를 필요로하는 클라이언트 측에서

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

: 그렇지 않으면 SSE 연결이 개발 서버를 차단하기 때문에 그냥 응용 프로그램을 실행할 때 스레딩을 사용해야합니다 서버에서 푸시됩니다.

var source = new EventSource('/stream'); 
source.onmessage = function (event) { 
    alert(event.data); 
}; 

서버 전송 이벤트는 최근 파이어 폭스, 크롬 및 사파리 브라우저 supported이다. Internet Explorer가 이전 버전의 브라우저

  • EventSource.js을 지원하기 위해 권장되는 두 Polyfills이 있습니다 아직 서버 전송 이벤트를 지원하지 않지만, 버전 10에서 그들을 지원하기 위해 예상된다
  • jquery.eventsource
+0

안녕하세요 @ PeterSmith, 그러나,이 방법을 시도, 경고 (event.data) 절대로 나타납니다. 포트 8000에서 포트 801을 실행하고 포트 8001에서 푸시 프로그램을 실행합니다. 따라서 "var source = new EventSource ('http : // localhost : 8001/push');" Flask 앱에는 사용자가 무언가를 게시 할 수있는 페이지가 있습니다. 게시물은 다른 모든 사용자가 브로드 캐스트하고 수신합니다. 아이디어가 있습니까? –

+0

왜 다른 포트에서 밀어 넣기를 실행합니까? SSE에 대한 한 가지 이유는 앱이 정상적인 http 이상으로 실행된다는 것입니다. 당신은 어떻게 당신의 플라스크 애플 리케이션을 실행 했습니까? 개발 서버를 통해? threaded = True를 추가 했습니까? 어떤 브라우저를 사용하고 있습니까? –

+0

안녕하세요. @PeterHoffmann, 나는 토네이도를 Flask와 함께 사용합니다. 토네이도에 앱 인스턴스와 푸셔 인스턴스를 함께 넣을 수 있습니까? 다른 처리기를 말해봐? 멀티 스레드를 설정해야합니까? –

5

로 후속 조치는 @peter-hoffmann's answer으로, 특히 서버 전송 이벤트를 처리하기 위해 Flask 확장을 작성했습니다. Flask-SSE이라고하며 available on PyPI입니다.설치하려면 실행

$ pip install flask-sse 

당신은 다음과 같이 사용할 수 있습니다 :

from flask import Flask 
from flask_sse import sse 

app = Flask(__name__) 
app.config["REDIS_URL"] = "redis://localhost" 
app.register_blueprint(sse, url_prefix='/stream') 

@app.route('/send') 
def send_message(): 
    sse.publish({"message": "Hello!"}, type='greeting') 
    return "Message sent!" 

그리고 자바 스크립트에서 이벤트 스트림에 연결하기 위해서는 다음과 같이 작동

var source = new EventSource("{{ url_for('sse.stream') }}"); 
source.addEventListener('greeting', function(event) { 
    var data = JSON.parse(event.data); 
    // do what you want with this data 
}, false); 

Documentation is available on ReadTheDocs. pub/sub를 처리하려면 실행중인 Redis 서버가 필요합니다.