使用粘性会话和 websocket 进行扩展

Posted

技术标签:

【中文标题】使用粘性会话和 websocket 进行扩展【英文标题】:Scaling with sticky sessions and websockets 【发布时间】:2018-07-01 04:02:54 【问题描述】:

最初,我们有两个带有 node.js 的 AWS EC2 实例,它们在带有粘性会话的负载均衡器后面运行。随着负载的增加,会添加更多实例。

但我们正面临这种方法的问题。由于外出申请主要针对研讨会,负载通常会在短时间内增加(研讨会开始),并且每个研讨会参与者对前两个实例都有一个粘性会话,而新的几乎没有。因此,性能一直很差。

首先想到的是:让我们禁用粘性会话。但这会破坏我们的 websocket,因为它们需要粘性会话(至少这是我读过的)。另一个问题是减少负载。实例关闭,套接字连接也丢失。

有没有办法在实例之间转移用户会话或让 websockets 在没有粘性会话的情况下工作(可能使用 Redis)?

【问题讨论】:

听起来你需要pub/sub broker 实际上我们正在使用 pubsub 和 redis,但是如果没有粘性会话,则无法建立 websocket 连接。 你的问题被标记为ELB,你知道ALB 不,我不是。基于内容的路由似乎是我的问题的解决方案。谢谢! 【参考方案1】:

解决方案是Application Load Balancer(请参阅comment)。

    起初我们不得不禁用轮询,因为这不适用于其余部分。这是通过手动定义传输来完成的。

    let iosocket = io('', 
        path: '/socket.io-client'
        transports: ['websocket']
    

    之后,我们设置了一个标准的应用程序负载均衡器,其中包含两个目标组:一个用于 websocket,另一个用于所有其他请求。 websocket 目标组的规则通过正则表达式匹配特定路径:

    最后一个问题是扩展:如果其中一个实例由于集群连接上的负载较低而关闭,则可能会丢失。在客户端断开连接后(在我们的例子中是一个角度应用程序),通过简单的重新连接来解决这个问题:

    [...]
    this.socket.on('disconnect', () => 
        // Reconnect after connection loss
        this.connect();
    );
    [...]
    

【讨论】:

以上是关于使用粘性会话和 websocket 进行扩展的主要内容,如果未能解决你的问题,请参考以下文章

使用 TCP 负载均衡器代理 WebSockets 而没有粘性会话

Websocket应用程序的nginx-ingress粘性会话

如何使用 docker swarm 保持粘性会话(会话持久性)?

如何使用容器对具有(长期)粘性会话的应用程序进行零停机滚动更新

负载均衡器粘性会话和非常旧的 Web 服务

会话粘性通常会提高 Rails 应用程序的性能吗?