首页 文章

TCP配置的Amazon Elastic Load Balancer上的Socket.io Websockets

提问于
浏览
16

我打算在EC2上设置一组运行Socket.io的NodeJS应用服务器,我想使用Elastic Load Balancer在它们之间传播负载 . 我知道ELB不支持开箱即用的Websockets,但我可以使用here in Scenario 2描述的设置 .

但是,如the blog post中所述,我注意到此设置不提供会话关联或源IP信息:

我们不能使用此设置具有Session Affinity或X-Forward标头,因为ELB不解析HTTP消息,因此无法匹配cookie以确保Session Affinity或Inject特殊的X-Forward标头 .

在这种情况下,Socket.io仍然会工作吗?或者是否有另一种方法可以在SSL负载均衡器后面安装一组Socket.io应用服务器?

编辑:蒂姆卡斯韦尔谈到这样做已经here . 有没有解释如何设置的帖子?再次,这里没有会话粘性,但似乎工作正常 .

顺便说一句,websockets实际上是否需要粘性会话?信息是作为新的和单独的请求传播还是只有一个请求连接,所有信息都会移动?

4 回答

  • 12

    您现在可以使用AWS最近推出的新应用程序负载均衡器 .

    只需用ALB(应用程序负载均衡器)替换ELB(现在称为Classic负载均衡器)并启用粘性会话 .

    ALB支持Web套接字 . 这应该可以解决问题 .

    https://aws.amazon.com/blogs/aws/new-aws-application-load-balancer/

    http://docs.aws.amazon.com/elasticloadbalancing/latest/application/introduction.html

  • -1

    即使使用TCP ELB,Socket.io也无法开箱即用,因为它在将连接升级到websockets之前会发出两个HTTP请求 .

    第一个连接用于 Build 协议,因为socket.io不仅支持websockets .

    GET /socket.io/1/?t=1360136617252 HTTP/1.1
    User-Agent: node-XMLHttpRequest
    Accept: */*
    Host: localhost:9999
    Connection: keep-alive
    
    HTTP/1.1 200 OK
    Content-Type: text/plain
    Date: Wed, 06 Feb 2013 07:43:37 GMT
    Connection: keep-alive
    Transfer-Encoding: chunked
    
    47
    xX_HbcG1DN_nufWddblv:60:60:websocket,htmlfile,xhr-polling,jsonp-polling
    0
    

    第二个请求用于实际升级连接:

    GET /socket.io/1/websocket/xX_HbcG1DN_nufWddblv HTTP/1.1
    Connection: Upgrade
    Upgrade: websocket
    Sec-WebSocket-Version: 13
    Sec-WebSocket-Key: MTMtMTM2MDEzNjYxNzMxOA==
    Host: localhost:9999
    
    HTTP/1.1 101 Switching Protocols
    Upgrade: websocket
    Connection: Upgrade
    Sec-WebSocket-Accept: 249I3zzVp0SzEn0Te2RLp0iS/z0=
    

    您可以在上面的示例中看到 xX_HbcG1DN_nufWddblv 是请求之间的共享密钥 . 这就是问题 . ELB执行循环路由,这意味着升级请求命中服务器而不是参与初始协商 . 因此,服务器不知道客户端是谁 .

    内存状态数据是负载 balancer 的敌人 . 值得庆幸的是,socket.io支持使用Redis来存储数据 . 如果您与多台服务器共享redis连接,它们基本上共享所有客户端的会话 .

    有关设置Redis的详细信息,请参阅socket.io wiki page .

  • 15

    正如我在帖子中提到的,我们只使用ELB来跨ssl终止并在支持websockets的http代理服务器集群之间进行负载 balancer . ELB不直接与websocket服务器通信 . HTTP代理集群处理查找正确的socket.io服务器以连接以确保会话粘性 .

  • 5

    当您在具有负载 balancer 器/反向代理,路由器等的 Cloud 中运行服务器时,您需要将其配置为正常工作,尤其是在您将服务器扩展为使用多个实例时 .

    Socket.io,SockJS和类似库的一个约束是它们需要不断地与服务器的同一个实例进行通信 . 当只有一个服务器实例时,它们可以很好地工作 .

    当您在 Cloud 环境中扩展应用程序时,负载均衡器(在Cloud Foundry的情况下为Nginx)将接管,并且请求将被发送到不同的实例,从而导致Socket.io中断 .

    为了在这种情况下提供帮助,负载均衡器具有称为“粘性会话”的功能,即“会话亲和力” . 主要思想是,如果设置了此属性,则在第一个负载 balancer 请求之后,所有以下请求将转到同一服务器实例 .

    在Cloud Foundry中,为设置cookie jsessionid的应用程序启用基于cookie的粘性会话 .

    注意:jsessionid是常用于跟踪Java / Spring应用程序中的会话的cookie名称 . Cloud Foundry简单地将其作为所有框架的粘性会话cookie .

    因此,所有应用程序需要做的是设置一个名为jsessionid的cookie来使socket.io工作 .

    app.use(cookieParser); app.use(express.session({store:sessionStore,key:'jsessionid',secret:'your secret here'}));

    所以这些是步骤:

    Express设置名为jsessionid的会话cookie . 当socket.io连接时,它使用相同的cookie并命中负载均衡器负载均衡器始终将其路由到设置cookie的同一服务器 . 如果使用应用程序负载均衡器,则粘性会话设置处于目标组级别

相关问题