Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WebSocket handshake in Node.JS, Socket.IO and Clusters not working

I having a problem with clustering my application with Node.js, socket.io and node.js clusters.

I using the socket.io-redis to share the information for all workers, but is not working.

My code:

var cluster   = require('cluster');
var numCPUs = require('os').cpus().length;

if (cluster.isMaster) {   
  // Fork workers.
  for (var i = 0; i < numCPUs; i++) {      
    cluster.fork();
  }

  cluster.on('exit', function(worker, code, signal) {
    console.log('worker ' + worker.process.pid + ' died');
  });
} else {

    ...

         var express   = require("express");
         //Server
         var server = express();
         //Socket.io
         var http  = require('http').Server(server);
         var io    = require('socket.io')(http);
         var redis_io = require('socket.io-redis'); 
         var redis = require("redis");

         io.adapter(redis_io({host: "127.0.0.1", port: 6379 })); 

    ...
}

In client, i get errors in handshake like 400 error or WebSocket is closed before the connection is established.

What i can do to solve this?

Im using the last version of node.js and socket.io

Thanks!

like image 881
GabrielBiga Avatar asked Oct 15 '14 04:10

GabrielBiga


People also ask

Is Socket.IO compatible with WebSocket?

Although Socket.IO indeed uses WebSocket for transport when possible, it adds additional metadata to each packet. That is why a WebSocket client will not be able to successfully connect to a Socket.IO server, and a Socket.IO client will not be able to connect to a plain WebSocket server either.

Does Nodejs support WebSockets?

Node. js can maintain many hundreds of WebSockets connections simultaneously. WebSockets on the server can become complicated as the connection upgrade from HTTP to WebSockets requires handling.

How many WebSocket connections can Nodejs handle?

The theoretical limit is 65k connections per IP address but the actual limit is often more like 20k, so we use multiple addresses to connect 20k to each (50 * 20k = 1 mil).

What is handshake in WebSocket?

The handshake starts with an HTTP request/response, allowing servers to handle HTTP connections as well as WebSocket connections on the same port. Once the connection is established, communication switches to a bidirectional binary protocol which does not conform to the HTTP protocol.


1 Answers

I had this same problem and it took me a while to figure it out. A bit of research explained that it is because some of the transports, like long-polling, need to make multiple requests in order to establish the optimal connection. There is state held across requests, so if different consecutive requests get routed to different cluster workers, the connection fails.

There is a page about it at http://socket.io/docs/using-multiple-nodes/ which cites a custom cluster module called sticky-session which works around this: https://github.com/indutny/sticky-session

I really did not want to use it since that basically ignores all the work the node.js team has been investing in the TCP load balancing behind the cluster module.

Since the Web Socket protocol itself only needs a single connection, I was able to work around this by forcing websocket to be the first and only transport. I can do this because I control the client and server. For a public web page, this may not be safe for you to do since you have to worry about browser compatibility. In my case, the client is a mobile app.

Here is the JavaScript client code I put into my test page (again, the real client is a mobile app, so my web page here is really just an aid to help build and test):

var socket = io('http://localhost:8080/', {
  transports: [ 'websocket' ]
});
like image 183
Brandon Avatar answered Oct 18 '22 20:10

Brandon