4
votes

I set up two EC2 Instances on AWS running behind the Load Balancer, but socket.io breaks when twos instance are running. I assume that as ELB round robins between instances and Socket.io sends requests before updating to Websockets this is causing socket io to break (Session ID unknown). I thought that by using shared session store on Redis , Socket.io would work since all instances would have access to sessions.

I have a small app developed in Node.js(more specifically Sails.js) just for testing. I managed to configure ELB to support Websockets in TCP mode, forwarding the requests to (Phusion Passenger + NGINX) which runs the Sails.js app.

The app uses Redis running on amazon Elasticache for SESSIONS and SOCKETS. If I test both instances separately without ELB, I see that Redis is working for Sockets as the messages are sent and received in both instances.

Is shared sessions enough to make Socket.io work? Or I need sticky sessions in the ELB to forward clients to same instances?

I chose ELB because is easier to add and remove instances dynamically, which is complicated with NGINX(Free) or HAProxy.

Any Ideas?

1
I have the same problem. How did you fix the problem ? Do you use socket.io-redis ?Grégoire Motot
@grégoire-motot, I ended up using socket.io and socket-io-redis with websockets only. To use other transports such as XHR Polling or JSONP Polling you need to have sticky sessions. You might find this article useful Load-balancing Websockets on EC2Lucas Lima

1 Answers

0
votes

When you run a server in a cloud that has a load-balancer/reverse proxy, routers etc, you need to configure it to work properly, especially when you scale the server to use multiple instances.

One of the constraints Socket.io, SockJS and similar libraries have is that they need to continuously talk to the same instance of the server. They work perfectly well when there is only 1 instance of the server.

When you scale your app in a cloud environment, the load balancer (Nginx in the case of Cloud Foundry) will take over, and the requests will be sent to different instances causing Socket.io to break.

To help in such situations, load balancers have a feature called 'sticky sessions' aka 'session affinity'. The main idea is that if this property is set, then after the first load-balanced request, all the following requests will go to the same server instance.

In Cloud Foundry, cookie-based sticky sessions are enabled for apps that set the cookie jsessionid.

Note: jsessionid is the cookie name commonly used to track sessions in Java/Spring applications. Cloud Foundry is simply adopting that as the sticky session cookie for all frameworks.

So, all the apps need to do is to set a cookie with the name jsessionid to make socket.io work.

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

So these are the steps:

  1. Express sets a session cookie with name jsessionid.
  2. When socket.io connects, it uses that same cookie and hits the load balancer
  3. The load balancer always routes it to the same server that the cookie was set in.
  4. If you are using Application Load Balancer then Sticky session settings is at target group level