使用 WebSockets 扩展 Flask REST API
Extending Flask REST API with WebSockets
我目前正在扩展我现有的 REST API 使用 Flask-RESTPlus 创建并支持 WebSocket。这个想法是创建一个 Web Thing Model 兼容的 Web 事物(网关)。我用例中的 "Things" 是动态添加或删除的。
当前设置允许消费者从事物中获取最新值,例如温度传感器,使用对 /thingId/properties/temperature 的 HTTP GET 请求。这些值实际上是从 Kafka 消费并临时存储在 Redis 中。
现在我想知道如何扩展此设置并让消费者不仅可以轮询最新值,还可以使用 WebSockets 订阅事物的 属性。我有一个可行的解决方案,我为每个 属性 创建 "Rooms",但这需要两个独立的服务器和端点的副本。
对于 REST,我有
@app.route('/<thingId>/properties/<propertyId>')
# get latest datapoint
return latestDatapoint
对于 Flask-SocketIO 我有
@socketio.on('join')
def on_join(data):
username = data['username']
room = data['room'] # e.g. /thingId/properties/temperature
join_room(room)
send(username + ' has entered the room.', room=room)
然后我将数据从 Kafka 转发到正确的房间。
在客户端,我需要连接到 WebSocket 服务器并加入房间
socket.on('connection', function(socket){
socket.emit('join', 'some room');
});
这个实现有效,但我强烈希望有一个替代工作流,如下图所示,其中客户端连接到 REST API 中使用的相同端点,但使用 WebSocket 协议而不是加入房间等
你知道这是否已经存在或是否可行?
I have a working solution where I create "Rooms" for each property, but this requires two separate servers and duplication of endpoints.
Socket.IO 服务器和您的 HTTP 服务器不一定需要分开,在所有支持的配置中,您可以使用单个服务器托管 HTTP 和 Socket.IO 应用程序。
我也没有看到端点重复,但这可能是因为您认为 Socket.IO 事件处理程序是端点,而实际上它们不是。 Socket.IO 在 HTTP 意义上有一个端点,因为所有 Socket.IO 流量都在一个 URL 上传输。您的事件处理程序就是在 Socket.IO 端点上弹出某些事件时调用的函数。
where the client connects to the same endpoint used in the REST API, but with the WebSocket protocol instead of joining rooms etc.
所以您希望您的客户端为其想要观看的每个事物建立一个单独的 WebSocket 连接?这似乎有点资源密集,对我来说不是很可扩展。如果客户端需要观看 100 个东西,那么它就必须维护 100 个 WebSocket 连接。请记住,大多数浏览器限制了它们一次可以打开的 WebSocket 连接数,包括每页和全局。
Socket.IO 是建立在 WebSocket 和 HTTP 之上的更高级别的协议。如果您仍然更喜欢直接使用 WebSocket,那么您可以使用任何可用的开源 WebSocket 服务器并使用它而不是 Socket.IO 来实现您的应用程序。以下是 Python 的几个选项:
- eventlet
- gevent-websocket
- websockets(异步)
- Tornado(异步)
您将失去一些 Socket.IO 提供的非常方便的东西:
- 自动重新连接
- 通过长轮询自动支持非 WebSocket 客户端
- 基于事件的调度
- 房间
所以你需要确保这些不是重要的特性,或者你可以直接在 WebSocket 服务器上自己实现它们。
我目前正在扩展我现有的 REST API 使用 Flask-RESTPlus 创建并支持 WebSocket。这个想法是创建一个 Web Thing Model 兼容的 Web 事物(网关)。我用例中的 "Things" 是动态添加或删除的。
当前设置允许消费者从事物中获取最新值,例如温度传感器,使用对 /thingId/properties/temperature 的 HTTP GET 请求。这些值实际上是从 Kafka 消费并临时存储在 Redis 中。
现在我想知道如何扩展此设置并让消费者不仅可以轮询最新值,还可以使用 WebSockets 订阅事物的 属性。我有一个可行的解决方案,我为每个 属性 创建 "Rooms",但这需要两个独立的服务器和端点的副本。
对于 REST,我有
@app.route('/<thingId>/properties/<propertyId>')
# get latest datapoint
return latestDatapoint
对于 Flask-SocketIO 我有
@socketio.on('join')
def on_join(data):
username = data['username']
room = data['room'] # e.g. /thingId/properties/temperature
join_room(room)
send(username + ' has entered the room.', room=room)
然后我将数据从 Kafka 转发到正确的房间。 在客户端,我需要连接到 WebSocket 服务器并加入房间
socket.on('connection', function(socket){
socket.emit('join', 'some room');
});
这个实现有效,但我强烈希望有一个替代工作流,如下图所示,其中客户端连接到 REST API 中使用的相同端点,但使用 WebSocket 协议而不是加入房间等
你知道这是否已经存在或是否可行?
I have a working solution where I create "Rooms" for each property, but this requires two separate servers and duplication of endpoints.
Socket.IO 服务器和您的 HTTP 服务器不一定需要分开,在所有支持的配置中,您可以使用单个服务器托管 HTTP 和 Socket.IO 应用程序。
我也没有看到端点重复,但这可能是因为您认为 Socket.IO 事件处理程序是端点,而实际上它们不是。 Socket.IO 在 HTTP 意义上有一个端点,因为所有 Socket.IO 流量都在一个 URL 上传输。您的事件处理程序就是在 Socket.IO 端点上弹出某些事件时调用的函数。
where the client connects to the same endpoint used in the REST API, but with the WebSocket protocol instead of joining rooms etc.
所以您希望您的客户端为其想要观看的每个事物建立一个单独的 WebSocket 连接?这似乎有点资源密集,对我来说不是很可扩展。如果客户端需要观看 100 个东西,那么它就必须维护 100 个 WebSocket 连接。请记住,大多数浏览器限制了它们一次可以打开的 WebSocket 连接数,包括每页和全局。
Socket.IO 是建立在 WebSocket 和 HTTP 之上的更高级别的协议。如果您仍然更喜欢直接使用 WebSocket,那么您可以使用任何可用的开源 WebSocket 服务器并使用它而不是 Socket.IO 来实现您的应用程序。以下是 Python 的几个选项:
- eventlet
- gevent-websocket
- websockets(异步)
- Tornado(异步)
您将失去一些 Socket.IO 提供的非常方便的东西:
- 自动重新连接
- 通过长轮询自动支持非 WebSocket 客户端
- 基于事件的调度
- 房间
所以你需要确保这些不是重要的特性,或者你可以直接在 WebSocket 服务器上自己实现它们。