node.js - Node Cluster issue using Socket.io and Redis -
ok, have express-powered api have socket.io running receive/send realtime events...all works dandy. need cluster app. set based on below code. spin workers, connections , works, except fact can't "blast" socket.io connections. here setup (taken this):
var express = require('express'), cluster = require('cluster'), net = require('net'), sio = require('socket.io'), sio_redis = require('socket.io-redis'); var port = 3000, num_processes = require('os').cpus().length; if (cluster.ismaster) { // stores our workers. need keep them able reference // them based on source ip address. it's useful auto-restart, // example. var workers = []; // helper function spawning worker @ index 'i'. var spawn = function(i) { workers[i] = cluster.fork(); // optional: restart worker on exit workers[i].on('exit', function(worker, code, signal) { console.log('respawning worker', i); spawn(i); }); }; // spawn workers. (var = 0; < num_processes; i++) { spawn(i); } // helper function getting worker index based on ip address. // hot path should fast. way works // converting ip address number removing dots, // compressing number of slots have. // // compared against "real" hashing (from sticky-session code) , // "real" ip number conversion, function on par in terms of // worker index distribution faster. var workerindex = function (ip, len) { var _ip = ip.split(/['.'|':']/), arr = []; (el in _ip) { if (_ip[el] == '') { arr.push(0); } else { arr.push(parseint(_ip[el], 16)); } } return number(arr.join('')) % len; } // create outside facing server listening on our port. var server = net.createserver({ pauseonconnect: true }, function(connection) { // received connection , need pass appropriate // worker. worker connection's source ip , pass // connection. var worker = workers[worker_index(connection.remoteaddress, num_processes)]; worker.send('sticky-session:connection', connection); }).listen(port); } else { // note don't use port here because master listens on us. var app = new express(); // here might use middleware, attach routes, etc. // don't expose our internal server outside. var server = app.listen(0, 'localhost'), io = sio(server); // tell socket.io use redis adapter. default, redis // server assumed on localhost:6379. don't have // specify them explicitly unless want change them. io.adapter(sio_redis({ host: 'localhost', port: 6379 })); // here might use socket.io middleware authorization etc. // listen messages sent master. ignore else. process.on('message', function(message, connection) { if (message !== 'sticky-session:connection') { return; } // emulate connection event on server emitting // event connection master sent us. server.emit('connection', connection); connection.resume(); }); }
so connect various machines test concurrency, workers thing , good, when io connection, i'm logging total "connected" count , it's 1 per instance. need way
allclusterforks.emit(stuff)
i connection on correct worker pid, "all connections" returns 1.
io.on('connection', function(socket) { console.log('connected worker %s', process.pid); console.log("adapter rooms %s ", io.sockets.adapter.rooms); console.log("adapter sids %s ", io.sockets.adapter.sids); console.log("sockets connected %s ", object.keys(io.sockets.connected).length); });
i can see subscribe/unsubscribe coming in using redis monitor
1454701383.188231 [0 127.0.0.1:63150] "subscribe" "socket.io#/#gxjscuuuvqgzsyjfaaaa#" 1454701419.130100 [0 127.0.0.1:63167] "subscribe" "socket.io#/#geysvysd5zasi7egaaaa#" 1454701433.842727 [0 127.0.0.1:63167] "unsubscribe" "socket.io#/#geysvysd5zasi7egaaaa#" 1454701444.630427 [0 127.0.0.1:63150] "unsubscribe" "socket.io#/#gxjscuuuvqgzsyjfaaaa#"
these connections 2 different machines, expect using socket io redis adapter these subscriptions coming in on same redis connection, different.
am totally missing something? there's surprising lack of documentation/articles out there aren't either outdated/wrong/ambiguous.
edit: node v5.3.0 redis v3.0.6 socket.io v1.3.7
so if comes across this, figured out "looking" @ counts of connected sockets across processes not thing, broadcasting or emitting them is. i've been "testing" no reason. works expected. rewriting socket.io-redis adapter allow checking counts across processes.
there pull request few years ago implement support trying do. https://github.com/socketio/socket.io-redis/pull/15 , might try cleaning , re-submitting.
Comments
Post a Comment