Socket.io - using multiple nodes

So I was looking for launching socket.io for multiple processes.

The guide here: https://socket.io/docs/using-multiple-nodes/ left me some questions.

It mentions using nginx config to load balance between socket.io processes, but also mentions using the built-in cluster module in Node.js below.

Should I use nginx AND cluster module in Node.js for this?

Also how do I tell if load balancing is working?

I tested it using the nginx option with two socket.io processes running using a redis adapter and using a cluster module.

This is what I had in my nginx config:

http {

        upstream io_nodes {
        ip_hash;
        server 127.0.0.1:6001;
        server 127.0.0.1:6002;
        }

        server {
        listen 3000;
        server_name example.com;
        location / {
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
        proxy_http_version 1.1;
        proxy_pass http://io_nodes;
        }
        }

      

This is an example of my socket.io code (most of it is taken from here: https://github.com/elad/node-cluster-socket.io ):

var express = require('express'),
    cluster = require('cluster'),
    net = require('net'),
    redis = require('redis'),
    sio = require('socket.io'),
    sio_redis = require('socket.io-redis');

var port = 6001,
    num_processes = require('os').cpus().length;

if (cluster.isMaster) {
    console.log('is master 6001');
    // This stores our workers. We need to keep them to be able to reference
    // them based on source IP address. It also useful for auto-restart,
    // for example.
    var workers = [];

    // Helper function for spawning worker at index 'i'.
    var spawn = function(i) {
        workers[i] = cluster.fork();

        // Optional: Restart worker on exit
        workers[i].on('exit', function(code, signal) {
            console.log('respawning worker', i);
            spawn(i);
        });
    };

    // Spawn workers.
    for (var i = 0; i < num_processes; i++) {
        spawn(i);
    }

    // Helper function for getting a worker index based on IP address.
    // This is a hot path so it should be really fast. The way it works
    // is by converting the IP address to a number by removing non numeric
  // characters, then compressing it to the number of slots we have.
    //
    // Compared against "real" hashing (from the sticky-session code) and
    // "real" IP number conversion, this function is on par in terms of
    // worker index distribution only much faster.
    var worker_index = function(ip, len) {
        var s = '';
        for (var i = 0, _len = ip.length; i < _len; i++) {
            if (!isNaN(ip[i])) {
                s += ip[i];
            }
        }

        return Number(s) % len;
    };

    // Create the outside facing server listening on our port.
    var server = net.createServer({ pauseOnConnect: true }, function(connection) {
        // We received a connection and need to pass it to the appropriate
        // worker. Get the worker for this connection source IP and pass
        // it the connection.
        var worker = workers[worker_index(connection.remoteAddress, num_processes)];
        worker.send('sticky-session:connection', connection);
    }).listen(port);
} else {
    // Note we don't use a port here because the master listens on it for us.
    var app = new express();

    // Here you might use middleware, attach routes, etc.

    // Don't expose our internal server to the outside.
    var server = app.listen(0, 'localhost'),
        io = sio(server);

    // Tell Socket.IO to use the redis adapter. By default, the redis
    // server is assumed to be on localhost:6379. You don't have to
    // specify them explicitly unless you want to change them.
    io.adapter(sio_redis({ host: 'localhost', port: 6379 }));

    // Here you might use Socket.IO middleware for authorization etc.
        io.on('connection', function(socket) {
        console.log('port 6001');
        console.log(socket.id);
    });
    // Listen to messages sent from the master. Ignore everything else.
    process.on('message', function(message, connection) {
        if (message !== 'sticky-session:connection') {
            return;
        }
        // Emulate a connection event on the server by emitting the
        // event with the connection the master sent us.
        server.emit('connection', connection);

        connection.resume();
    });
}

      

The links worked fine with this, although I tested everything locally.

How can I know if it is working correctly? Every time a client connects, it seems to be connecting to a socket.io process on the port 6001

.

The client connection code connects to the port 3000

.

+3


source to share


2 answers


Should I use nginx AND cluster module in Node.js for this?

If all your server processes are on the same machine, you can use the cluster module without NGINX.

If you are running multiple server computers, you will need a piece of networking infrastructure like NGINX to load balance between different servers, as a Node.js cluster cannot do this for you.



And you can use both together (balancing multiple servers is done with something like NGINX and each server with clustering on each server). The key point here is that the Node.js cluster only distributes the load between different processes on the same host.

Also how do I tell if load balancing is working?

You can log each process the activity it handles and add the process id as part of the logging, and if you load the server with multiple requests at the same time, you should see each process being handled by each process. If you are doing actual load testing, you should increase the throughput significantly when clustering is enabled and works against using clustering. Keep in mind that overall throughput depends on where your bottlenecks are, if your server is actually database bound and all the clustered processes are using the same database, you can hardly benefit from clustering the Node process .js. If, on the other hand, your Node.js process is computationally intensive and you have multiple cores on your server,you can get a significant benefit from clustering.

+1


source


Adding more points to the solution above.

Also how do I tell if load balancing is working?



I use node-debug for this, it opens multiple debuggers according to the number of threads. Now you can add a checkpoint to check if the load is distributed correctly.

0


source







All Articles