我有一个socket.io聊天室,当我们在一台机器上运行时,它的流量越来越大。我们使用ws库为套接字运行基准测试,它们的性能要好得多,这样可以更好地利用我们的硬件。这需要重写我们的应用程序。
我们的socket.io应用程序允许用户创建使用命名空间实现的私人聊天室。 E.g
localhost:8080/room/1
localhost:8080/room/2
localhost:8080/room/3
当一切都在一个实例中时,这很容易,但现在我们正在寻求将这个容量扩展到多个节点。
我们在亚马逊的云中运行此实例。以前看起来像缩放websockets是ELB的一个问题。我们注意到Amazon现在支持和支持websockets的应用程序负载均衡器。这听起来不错,但在阅读完文档之后我必须承认我并不知道这意味着什么。如果我使用带有数千个命名空间的socket.io,我只是将实例放在这个ALB后面,一切都会起作用吗?我的主要问题是:
如果x个用户加入了命名空间,ALB会自动将我的消息重定向到适当的用户吗?所以假设我在ALB后面运行了5个vanilla socket.io实例。用户1创建名称空间。几个小时后通过,用户99999来了,并希望加入这个命名空间,是否需要编写任何其他代码来执行此操作,或者alb会重定向所有应该去的地方吗?发送和接收消息也一样吗?
答案 0 :(得分:20)
虽然ALB会正确地对用户进行负载平衡,但您需要稍微调整一下代码,因为加入特定会议室的用户将分散在不同的服务器中。
在documentation socket.io中提供了一种方法:
现在您有多个Socket.IO节点接受连接,如果 你想向每个人(甚至是一个人)广播事件 某些房间)你需要一些方法来传递消息 流程或计算机。
负责路由消息的接口就是我们所说的 适配器。您可以在socket.io-adapter之上实现自己的 (通过继承)或者您可以使用我们提供的那个 Redis:socket.io-redis:
var io = require('socket.io')(3000);
var redis = require('socket.io-redis');
io.adapter(redis({ host: 'localhost', port: 6379 }));
ALB设置
我建议在ALB中启用粘性会话,否则socket.io握手在使用非websocket传输时会失败,例如长轮询,因为使用此传输的握手任务需要超过一个请求,您需要对同一服务器执行所有这些请求。
如果我想避免使用redis数据库。例如,如果我的房间是由用户创建的,则userA会创建一个房间 在实例4中,如果另一个用户想要加入这个房间,他们将如何 知道它在哪个实例上?我也需要适配器吗?
此备选方案的目标是将每个房间分配给特定的EC2实例。我们将使用ALB Routing
来实现这一目标N个房间> 1个实例。
您需要将房间网址更改为:
/i1/room/550
/i1/room/20
/i2/room/5
/i5/room/492
感:
/{instance-number}/room/{room-id}
这是必需的,因此ALB可以将每个房间路由到特定的实例。
创建N个目标组(N是您目前拥有的实例数)
将每个实例注册到每个目标组
目标群体&gt; <实例X目标组>目标标签&gt;编辑&gt;选择实例X&gt;添加到已注册的
Target group X > EC2 Instance X
Target group Y > EC2 Instance Y
编辑ALB目标规则
负载均衡器&gt;你的ALB&gt;听众&gt;查看/编辑规则
使用以下设置为每个目标组/实例创建一个规则:
/iX/room/*
instanceX
输入后进行此设置:
/i1/room/550
您将使用EC2实例1。/i2/room/200
将使用EC2实例2 等等。
现在,您必须制作自己的逻辑,以便在您的实例中保持房间平衡。 您不希望有一个实例托管几乎所有组。
我推荐第一种方法,因为它可以轻松自动缩放。