Jonathan Loiselle
Jonathan Loiselle

Reputation: 15

Why is my client receiving socket emits from all child node cluster workers when it should only be connected to one?

I'm trying to make a scalable socket connection handler using node.js, express, socket.io, cluster, socket.io-adapter-mongo, and mubsub. This is my first attempt to use sockets, so forgive me if I reveal my noobness here, but it is my understanding that a cluster worker can only emit to the sockets that are connected to it.

In my dev environment I have cluster forking 8 workers (number of cpus.)

I have my workers subscribe to mubsub db so that they will pick up events that are published from other workers.

if (cluster.isMaster) {

    var cpuCount = require("os").cpus().length;
    for (var cp = 0; cp < cpuCount; cp++) {
        cluster.fork();
    }
} else {

    io.adapter(mongo({ host: 'localhost', port: 27017, db: 'mubsub' }));

    var client = mubsub('mongodb://localhost:27017/mubsub');

    var channel = client.channel('test');

    channel.subscribe('testEvent', function (message) {
        console.log(message);
        io.sockets.emit('testEvent', {message: cluster.worker.id});
    });

    io.sockets.on('connection', function (socket) {
        console.log('connected to ' + cluster.worker.id);
        channel.publish('testEvent', { message: 'connection3' });
    });

    ...

    server.listen(8080);
}

So when I try to connect from the client, the 'connection' event fires and a single console log is written by the worker that receives the connection.

That event is published to the database only once.

Each worker is subscribed to that event, and should emit to all sockets connected to that worker.

For some reason though, my connected client receives 8 messages, one for each worker.

How is the client picking up the emits from workers it should not be connected to? Am I overlooking some cluster magic here?

Upvotes: 0

Views: 481

Answers (1)

nomDePlum
nomDePlum

Reputation: 101

Not sure what version you are using but this should be true for most current versions.

From the socket.io docs (http://socket.io/docs/server-api/#server#emit):

Server#emit
Emits an event to all connected clients. The following two are equivalent:

 var io = require('socket.io')();
 io.sockets.emit('an event sent to all connected clients');
 io.emit('an event sent to all connected clients');

So the method you are using will broadcast to all connected clients. If you want to split them across the workers this is something you need to manage.

There are a number of ways to address individual sockets(clients) that socket.ios API can help you with but probably best to refer to the docs for this:

http://socket.io/docs/rooms-and-namespaces/

Upvotes: 0

Related Questions