负载均衡Web Socket - AWS弹性负载均衡器

8

我有一个问题,关于如何使用AWS弹性负载均衡器来平衡WebSocket。

在AWS弹性负载均衡器后面有2个EC2实例。

当任何用户登录时,用户会话将与其中一台服务器建立连接,比如EC2实例1。现在,所有来自同一用户的请求将被路由到EC2实例1。

现在,我有一个来自不同系统的不同无状态请求。该请求将包含userId。这个请求可能最终会发送到EC2实例2。我们需要根据请求中的userId向用户发送通知。

现在:

1)假设用户会话与EC2实例1建立连接,但通知是从EC2实例2发起的。 我不确定如何在这种情况下通知用户浏览器。

2)WebSocket连接是否存在像64K这样的限制,以及如何在多个服务器之间进行处理,因为用户是通过负载均衡器进入的。

谢谢

3个回答

5

我只是在尝试理解Redis如何解决这个问题,因为事件发生和WebSocket会话位于两个不同的实例上。 - user1578872
说实话,我对Redis的模型不是很熟悉,但它似乎是最广泛使用/最简单的方法之一。无论如何,在理论上,它应该像这样工作:一个实例可以订阅事件,另一个实例可以发布它。Redis将通知已订阅的实例。还有两个有用的链接:https://redis.io/topics/pubsub https://robots.thoughtbot.com/redis-pub-sub-how-does-it-work 否则,我认为主要问题是以某种方式连接这两个服务器,它们必须通过通道进行通信。还有一些其他的“队列”工具。 - Lajos Veres

3

Websocket请求开始于HTTP通信,然后转为websocket。理论上,如果您可以在初始的HTTP请求中包含cookie,则ELB的粘性会话功能将允许您将websocket定向到特定的EC2实例。但是,您的websocket客户端可能不支持此功能。

更好的解决方案是使您的EC2实例无状态。将websocket会话数据存储在AWS Elasticache(Redis或Memcached)中,然后传入的连接将能够访问会话,而不管使用哪个EC2实例。

这种解决方案的优点是,您消除了对单个EC2实例的依赖,应用程序将更好地扩展和处理故障。

如果ELB有太多传入连接,则它应该自动缩放。虽然我找不到相关的参考资料。ELB相对缓慢地进行缩放——需要几分钟而不是几秒钟。如果您预计流量激增,则AWS可以通过支持请求为您“预热”更多的ELB资源。

此外,请考虑ELB的连接超时时间。默认情况下为60秒,可以通过AWS控制台或API进行增加。您的应用程序需要在超时之前发送至少1字节的流量,否则ELB将断开连接。


即使我使用Elasticcache缓存会话,Websocket也能正常工作吗?我认为,Websocket是与单个服务器建立连接的。 - user1578872
是的,一旦建立连接,它将在该连接持续期间继续访问同一EC2实例。在您的问题中,您提到了来自不同系统的不同无状态请求,这可能会被路由到不同的EC2实例,因为它是一个新的连接。如果多个连接需要共享会话数据,则Elasticcache是在多个EC2实例之间共享会话数据的一种方法。 - Steve E.
即使多个连接共享会话数据,如果无状态请求发送到实例1并且与实例2建立了WebSocket,那么该怎么办呢?在这种情况下,会话数据将在实例1和2中都可用。但是,如何从实例1向实例2发送WebSocket通知呢? - user1578872
这个情况要复杂一些。对于小规模项目,可以让与浏览器进行轮询的服务器进程查询Elasticache是否有变更,并将其转发给浏览器。而对于大规模项目,更可扩展的方式是使用一个消息处理过程来追踪实时连接,并结合像AWS SNS这样的队列服务,将通知定向发送到正确的目标位置。 - Steve E.
很抱歉,我还不太清楚。即使使用AWS SNS,如何从另一个实例通知呢?我可以从实例1和2公开一个Web服务并调用该服务,但这需要时间。正在寻找更好的解决方案。 - user1578872

1
最近我不得不将crossbar.io的Websockets与ALB连接起来。基本上有两件事需要考虑。1)您需要在目标组属性上设置粘性为1天。2)如果连接未升级,您需要在同一端口上返回静态网页,或者在一个单独的端口上提供一个带有自定义健康检查的静态网页,并在目标组上指定该端口。选择ALB而不是ELB,因为ALB支持ws://和wss://,只是缺少对Websockets的健康检查支持。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接