加载 balancing/routing 个使用 socketio 和 flask 制作的应用程序

load balancing/routing an application made with socketio and flask

在部署 Web 应用程序方面我有点菜鸟,想确保我正在构建的小应用程序能够与我尝试使用的技术一起工作。

我对flask有一些经验,但只用过测试服务器。我的理解是,使用 nginx 或 apache,如果我编写一个 flask 应用程序,每个访问我网站的用户都可以获得一个不同的 flask 应用程序实例,具体如何工作让我有点困惑。

我想制作的应用类似于chatrooms/a游戏,比如“among us”。当用户访问该网站时,他们会加入一个大“大厅”,并且可以加入一个已经存在的“房间”,或者启动一个新房间并生成一个 code/ID,他们可以将其传递给他们的朋友,以便他们的朋友们可以加入同一个会话(我认为可以为此使用 socketio“房间”)。

但是,如果每个客户端都连接到他们自己的 flask 实例,每个服务器实例都能够看到其他实例上的“房间”吗?假设我的应用程序变得非常流行,并且我想在将来跨多个 machines/AWS 实例扩展大厅,我现在可以做些什么来确保它有效吗?或者就 flask-socketio/nginx 堆栈而言,跨多台机器扩展等同于在一台机器上跨实例扩展。

基本上,我如何确保代码的大厅部分是可扩展的。我需要做些什么来确保每个用户都能够与其他用户连接到房间,即使他们获得了不同的 flask 应用程序实例?

我将专门针对 Socket.IO 服务回答这个问题。您的应用程序或您使用的第三方服务的其他功能可能需要它们自己对水平缩放的支持。

Flask-SocketIO 从一个实例扩展到两个或更多实例需要一个额外的部分,一个消息队列,通常是 Redis 或 RabbitMQ,尽管还有更多选项。

正如您在问题中明确指出的那样,当整个服务器处于单个实例中时,在托管应用程序的单个进程的内存中很容易获得诸如每个连接的客户端所在的房间等数据。

当您扩展到两个或更多实例时,您的客户端将被分区并随机分配到您的一台服务器。因此,您最终可能会在一个房间中的参与者也分布在多个服务器上。

为了让事情正常进行,服务器实例都连接到消息队列并使用消息来协调复杂的操作,例如向房间广播。

所以简而言之,要从一个实例扩展到多个实例,您需要做的就是部署一个消息队列,并更改 Flask-SocketIO 服务器以指示队列的位置。例如,这里是单实例服务器实例化:

from flask_socketio import SocketIO

socketio = SocketIO(app)

这是在本地主机的默认 6379 端口上使用 Redis 消息队列 运行 进行的初始化:

from flask_socketio import SocketIO

socketio = SocketIO(app, message_queue='redis://')

不需要更改应用程序代码,Flask-SocketIO 通过在队列上发布消息来为您完成所有实例之间的协调。

请注意,实例托管在同一服务器还是不同服务器上并不重要。重要的是它们连接到同一个消息队列,以便它们可以通信。