Flask:一个RESTful API和SocketIO服务器

19

背景

我正在尝试使用Flask-RESTful扩展创建一个简单的REST API。该API主要用于管理一个简单服务的用户的CRUD和身份验证。

我还在尝试使用Flask-SocketIO扩展创建一些Web套接字,这些用户将能够连接到并实时查看与使用该服务的其他人相关的数据更新。因此,我需要知道这些用户已经通过身份验证并被授权连接到某些套接字。

问题

然而,我遇到了一些设置上的问题。似乎我无法让这两个组件(REST API和SocketIO服务器)在同一个Flask实例上一起工作。原因是当我运行下面的代码时,要么REST API或SocketIO服务器会工作,但不能同时工作:

from flask import Flask
from flask_restful import Api
from flask.ext.socketio import SocketIO

app = Flask(__name__)

api = Api(app)
socketio = SocketIO(app)

# some test resources for the API and
# a test emitter statement for the SocketIO server
# are added here

if __name__ == '__main__':
    app.run(port=5000)
    socketio.run(app, port=5005)

问题

在这种设置中,典型的解决方案是同时运行两个不同的Flask实例吗?例如,我的SocketIO服务器是否必须向我的REST API发出请求,以检查特定用户是否已经被认证/授权连接到特定的socket?


如果您只使用 socketio.run(app, port=5005) 并尝试在端口5005上访问REST API,会发生什么? - Sean Vieira
@SeanVieira 出于某种原因,那很好地运作了... 我想我会把我的 API 和 sockets 放在同一个端口上。 - nmagerko
1个回答

32

您只需要运行socketio.run(app, port=5005)并在5005端口上访问REST API即可。

这样做的原因是因为,在幕后,Flask-SocketIO正在运行一个基于gevent(或者1.0版本中还可以使用eventlet)的事件驱动Web服务器 - 这个服务器直接处理websocket请求(使用您通过socketio.on修饰器注册的处理程序),并将非websocket请求传递给Flask。

您代码不能正常工作的原因是因为app.runsocketio.run都是阻塞操作。无论哪一个先运行,都会进入循环等待连接,从而不允许第二个启动。如果您确实需要在不同的端口上运行websocket连接,则需要在不同的进程中生成socketio或应用程序的run调用。


6
回答:非常好的回答,但我想指出 Flask-SocketIO 即将打破对 gevent 的独占依赖。 该扩展的开发版本1.0a1可以使用 gevent,eventlet或甚至普通的 Werkzeug(尽管后者无法运行 WebSocket支持)。 - Miguel Grinberg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接