node-cluster-socket.io icon indicating copy to clipboard operation
node-cluster-socket.io copied to clipboard

Can I use Master, and Workers process communication when also using Sticky Session?

Open Trysonic opened this issue 5 years ago • 0 comments

I'm trying to use sticky-session for socket.io as a load balancer.

I use this example from the main page:

    var express = require('express'),
        cluster = require('cluster'),
        net = require('net'),
        sio = require('socket.io'),
        sio_redis = require('socket.io-redis'),
        farmhash = require('farmhash');
    
    var port = 3000,
        num_processes = require('os').cpus().length;
    
    if (cluster.isMaster) {
    	// This stores our workers. We need to keep them to be able to reference
    	// them based on source IP address. It's 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) {
    		return farmhash.fingerprint32(ip) % len; // Farmhash is the fastest and works with IPv6, too
    	};
    
    	// 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's 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.
    
    	// 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();
    	});
    }

My problem are these lines:

	// 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();
	});

For my app, I need to use "process.on / process.send" communication, as well as "worker[worker_id].send" when in my Master cluster.

Is it banned to do so with sticky session? Can it break the communication?

I want to use something like that:

	process.on('message', function(message, connection) {
		if (message !== 'sticky-session:connection')
		{
			if(message.action == "calculX")
			{
				//redirect to function in this worker
			}	
			if(message.action == "calculY")
			{
				//redirect to function in this worker
			}				
			
			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();
	});

Is it allowed or will it break the "connection" system?

Thanks in advance.

Trysonic avatar Aug 08 '18 11:08 Trysonic