TCPconfiguration的Amazon Elastic Load Balancer上的Socket.io Websockets

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

正如博客文章中所述 ,我注意到这个设置没有提供会话关联或源IP信息:

我们不能使用Session Affinity和X-Forward头文件,因为ELB并不parsingHTTP消息,所以不可能匹配cookies来确保Session Affinity,也不能注入特殊的X-Forward头文件。

Socket.io在这种情况下还能工作吗? 或者还有另一种方法来在负载平衡器后面使用SSL来configuration一组Socket.io应用服务器?

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

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

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

只需将ELB(现在称为“经典负载平衡器”)replace为ALB(应用程序负载平衡器)并启用粘性会话即可。

ALB支持Web套接字。 这应该做的伎俩。

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

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

即使使用TCP ELB,Socket.io也不能正常工作,因为在将连接升级到websockets之前,它会发出两个HTTP请求。

第一个连接用于build立协议,因为socket.io支持的不仅仅是websocket。

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执行循环路由,这意味着升级请求会触及服务器,而不是参与初始协商。 因此,服务器不知道客户是谁。

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

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

正如我在文章中提到的,我们只使用ELB来终止和负载均衡,支持websocket的http代理服务器集群。 ELB不直接与websocket服务器通话。 HTTP代理群集处理查找正确的socket.io服务器连接,以确保会话粘性。

在具有负载平衡器/反向代理,路由器等的云中运行服务器时,需要将其configuration为正常工作,特别是在扩展服务器以使用多个实例时。

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

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

为了在这种情况下提供帮助,负载平衡器具有称为“粘性会话”(又称会话亲和性)的function。 主要思想是如果设置了这个属性,那么在第一个负载平衡的请求之后,所有下面的请求将会到同一个服务器实例。

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

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

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

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

所以这些是步骤:

Express使用名称jsessionid设置会话cookie。 当socket.io连接时,它使用同一个cookie,并访问负载均衡器负载均衡器始终将其路由到设置cookie的服务器。如果使用的是应用程序负载平衡器,则“粘滞会话”设置处于目标组级别