elad / node-cluster-socket.io

Writeup on how to make node.js cluster and socket.io play nice
421 stars 63 forks source link

Sticky sessions using client's custom data #19

Closed kuzinmv closed 8 years ago

kuzinmv commented 8 years ago

Hello @elad

Thank you for your great example of using socket.io and cluster. In front of me there was a similar problem, and your example is very helpful to understand.

I was a little modified your example, I would like to make the session became attached to specified worker process is not over IP, but for client's custom data. For example user ID.

example

I started working with Node.js not so long ago, could you leave a few comments about my solution.

Kind regards.

elad commented 8 years ago

Here's the relevant code you modified:

    // Create the outside facing server listening on our port.
    var server = net.createServer({ pauseOnConnect: true }, function(socket) {

        socket.on('readable', function () {
            var buffer = socket.read();
            if (!buffer) {
                return
            }
            var headers = buffer.toString();
            var to = headers.indexOf('HTTP');

            // Quick & dirty way to get query string params
            console.log(headers.substr(0, to));
            var url = headers.substr(0, to).replace('GET /','http://').replace('POST /', 'http://');
            var queryParams = qs.parse(urlHelper.parse(url).query);

            var index = queryParams.userId % num_processes;
            var worker = workers[index];

            worker.send({
                type:'sticky-session:connection',
                buffer: buffer.toString()
            }, socket);
        });

    }).listen(port);

The entire point of this writeup was to demonstrate file descriptor passing. You broke that by reading the data in the master and passing the data to the workers. This means the master holds all the connections and the workers simply get buffers. It's not going to scale well. Also, you're modifying the incoming data just to make it easier to parse... this is closer to the MITM attack than routing.

kuzinmv commented 8 years ago

Thanks for your reply!

I'll try to explain my problem completely. I need to develop a chat application, where one user can be connected using multiple devices with the same login. At the same time. And between these applications should sync data. These devices are likely to have a different IP address and will be redirected to different worker`s

If we use the cluster, we need to install additional software has to be exchanged between processes, Redis for example. I wanted to avoid this for specific reasons and group users by their username or ID on one particular worker.

Yes, it seems in some way to a MITM, but more importantly, that the master process reads once the data from the open connection, and as well as in your example, a worker sends a file descriptor and the data that he had already read.

Then a worker has himself read from a socket

// Listen to messages sent from the master. Ignore everything else.

process.on('message', function(message, socket) { if (message.type !== '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', socket);

// Call data event for socket with first chunk of client request
var buffer = Buffer.from(message.buffer);
socket.emit('data', buffer);

socket.resume();

});

Thanks again for your reply, I hope this letter has brought more clarity to my problem and the code that I sent to you earlier.

2016-05-28 14:48 GMT+07:00 Elad Efrat notifications@github.com:

Closed #19 https://github.com/elad/node-cluster-socket.io/issues/19.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/elad/node-cluster-socket.io/issues/19#event-675145631, or mute the thread https://github.com/notifications/unsubscribe/AGUK6IK7QsLELSoR3ICvtLRW17VAeBm0ks5qF_M-gaJpZM4Insbq .