如何在Flask框架中实现服务器推送?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在Flask框架中实现服务器推送?相关的知识,希望对你有一定的参考价值。
我正在尝试使用Flask micro-web框架上的服务器推送功能构建一个小型站点,但我不知道是否有一个框架可以直接使用。
我使用了Juggernaut,但它似乎与当前版本的redis-py不兼容,而Juggernaut最近已被弃用。
有没有人对我的案子有任何建议?
看看Server-Sent Events。 Server-Sent Events是一个浏览器API,可让您继续打开服务器的套接字,订阅更新流。有关更多信息,请阅读Alex MacCaw(Juggernaut的作者)在why he kills juggernaut上的帖子以及为什么更简单的Server-Sent事件在manny案例中比Websockets更适合工作。
协议非常简单。只需将mimetype text/event-stream
添加到您的回复中。浏览器将保持连接打开并监听更新。从服务器发送的事件是以data:
和后续换行符开头的一行文本。
data: this is a simple message
<blank line>
如果要交换结构化数据,只需将数据转储为json并通过线路发送json。
一个优点是您可以在Flask中使用SSE而无需额外的服务器。在github上有一个简单的chat application example,它使用redis作为pub / sub后端。
def event_stream():
pubsub = red.pubsub()
pubsub.subscribe('chat')
for message in pubsub.listen():
print message
yield 'data: %s
' % 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")
您不需要使用gunicorn来运行示例应用程序。只需确保在运行应用程序时使用线程,否则SSE连接将阻止您的开发服务器:
if __name__ == '__main__':
app.debug = True
app.run(threaded=True)
在客户端,您只需要一个javascript处理函数,当从服务器推送新消息时将调用该函数。
var source = new EventSource('/stream');
source.onmessage = function (event) {
alert(event.data);
};
最近的Firefox,Chrome和Safari浏览器的服务器发送事件是supported。 Internet Explorer尚不支持Server-Sent Events,但预计会在版本10中支持它们。有两种推荐的Polyfill支持旧版浏览器
作为@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!"
并且要从Javascript连接到事件流,它的工作方式如下:
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.请注意,您需要一个正在运行的Redis服务器来处理pub / sub。
Redis过度使用:使用服务器端事件
晚会(像往常一样),但恕我直言使用Redis可能是矫枉过正。
只要您在Python + Flask中工作,请考虑使用this excellent article by Panisuan Joe Chasinga中描述的生成器函数。它的要点是:
在您的客户端index.html中
var targetContainer = document.getElementById("target_div");
var eventSource = new EventSource("/stream")
eventSource.onmessage = function(e) {
targetContainer.innerHTML = e.data;
};
...
<div id="target_div">Watch this space...</div>
在Flask服务器中:
def get_message():
'''this could be any function that blocks until data is ready'''
time.sleep(1.0)
s = time.ctime(time.time())
return s
@app.route('/')
def root():
return render_template('index.html')
@app.route('/stream')
def stream():
def eventStream():
while True:
# wait for source data to be available, then push it
yield 'data: {}
'.format(get_message())
return Response(eventStream(), mimetype="text/event-stream")
以上是关于如何在Flask框架中实现服务器推送?的主要内容,如果未能解决你的问题,请参考以下文章