虽然ALB会正确地负载均衡用户,但您需要稍微调整代码,因为加入特定房间的用户将分散在不同的服务器上。
在他们的文档中,socket.io提供了一种方法来解决这个问题:
现在您有多个Socket.IO节点接受连接,如果您想向所有人(甚至是某个房间中的所有人)广播事件,则需要一些方法在进程或计算机之间传递消息。
负责路由消息的接口是我们所谓的Adapter。您可以在socket.io-adapter之上实现自己的Adapter(通过继承它),也可以使用我们在Redis之上提供的Adapter:socket.io-redis:
var io = require('socket.io')(3000);
var redis = require('socket.io-redis');
io.adapter(redis({ host: 'localhost', port: 6379 }));
ALB设置
我建议在您的ALB中启用粘性会话,否则,在使用非WebSocket传输(例如长轮询)时,Socket.io握手将失败,因为使用这些传输进行握手任务需要多个请求,而且您需要执行所有这些请求针对同一服务器。
![enter image description here](https://istack.dev59.com/oPaDc.webp)
使用ALB路由的替代方案,无需socket.io适配器。
如果我想避免使用redis数据库。例如,如果我的房间是由用户创建的,如果用户A在实例4上创建了一个房间,如果另一个用户想要加入这个房间,他们怎么知道它在哪个实例上?我也需要适配器吗?
这种替代方案的目标是将每个房间分配给特定的EC2实例。我们将使用ALB路由来实现这一目标。
N个房间 > 1个实例。
步骤1:
您需要将房间URL更改为类似以下内容的URL:
/i1/room/550
/i1/room/20
/i2/room/5
/i5/room/492
存在:
/{instance-number}/room/{room-id}
这是必需的,这样ALB才能将每个房间路由到特定的实例。
步骤2:
创建N个目标组(N是当前拥有的实例数量)
![Image](https://istack.dev59.com/0RJfW.webp)
步骤3:
将每个实例注册到每个目标组
目标组 > 实例X目标组> 目标选项卡 > 编辑 > 选择实例X > 添加到已注册列表
Target group X > EC2 Instance X
Target group Y > EC2 Instance Y
![图片描述](https://istack.dev59.com/IWsVu.webp)
第四步:
编辑ALB目标规则
负载均衡器>您的ALB>侦听器>查看/编辑规则
![图片描述](https://istack.dev59.com/8nxw6.webp)
第五步:
为每个目标组/实例创建一个规则,具有以下设置:
- IF > Path:
/iX/room/*
- THEN > forward to:
instanceX
![图片描述](https://istack.dev59.com/xViwE.webp)
![图片描述](https://istack.dev59.com/aCm5A.webp)
一旦您完成了这个设置,当您输入:
/i1/room/550
您将使用EC2实例1
/i2/room/200
将使用EC2实例2
等等。
现在,您需要自己制定逻辑,以便在您的实例之间平衡房间。 您不希望一个实例承载几乎所有的群组。
我建议使用第一个方法,因为它可以轻松地进行自动缩放。