elad / node-cluster-socket.io

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

How to use the example mentioned in node-cluster-socket.io to work with domains ? #14

Closed mukulgupta2507 closed 8 years ago

mukulgupta2507 commented 8 years ago

Hi Elad,

I'm struggling with a problem where I'm using using clusters along with domains. Due to this, my chat functionality has stopped working. The reason for this is handshaking is not working as it was in a single threaded environment. I'm planning to modify my existing code using your code but facing few issues:

Here is my code which I'm using right now:


'use strict';

// Set default node environment to development
process.env.NODE_ENV = process.env.NODE_ENV || 'development';

var express = require('express');
var mongoose = require('mongoose');
var config = require('./config/environment');
var session = require('express-session');
var FB = require('fb');
var redisStore = require('connect-redis')(session);
var crypto = require('crypto');
var fs = require('fs');
var cluster = require('cluster');
var domain = require('domain');

var socketIo = require('./config/socketio');

var REDIS = require('redis')

// redis clients
var store = REDIS.createClient();
//var pub = REDIS.createClient();
//var sub = REDIS.createClient();

var pub = REDIS.createClient(config.redis.port, config.redis.host, {return_buffers: true});
var sub = REDIS.createClient(config.redis.port, config.redis.host, {return_buffers: true});

function uuidFromBytes(rnd) {
  rnd[6] = (rnd[6] & 0x0f) | 0x40;
  rnd[8] = (rnd[8] & 0x3f) | 0x80;
  rnd = rnd.toString('hex').match(/(.{8})(.{4})(.{4})(.{4})(.{12})/);
  rnd.shift();
  return rnd.join('-');
}

if(cluster.isMaster) {
    var numWorkers = require('os').cpus().length;

    console.log('Master cluster setting up ' + numWorkers + ' workers...');

    for(var i = 0; i < numWorkers; i++) {
        cluster.fork();
    }

    cluster.on('online', function(worker) {
        console.log('Worker ' + worker.process.pid + ' is online');
    });

    cluster.on('exit', function(worker, code, signal) {
        console.log('Worker ' + worker.process.pid + ' died with code: ' + code + ', and signal: ' + signal);
        console.log('Starting a new worker');
        cluster.fork();
    });

} else {
    var d = domain.create ();
    d.on ("error", function (error){
      //something unexpected occurred
      console.error('uncaught error', error.stack);
      var killtimer = setTimeout(function()
      {
         process.exit(1);
      }, 30000);
      // But don't keep the process open just for that!
      killtimer.unref();
      //stop taking new requests.
      server.close();
      //Let the master know we're dead.  This will trigger a
      //'exit' in the cluster master, and then it will fork
      //a new worker.
      cluster.worker.exit();
    });

    // Connect to database
    mongoose.connect(config.mongo.uri, config.mongo.options);

    // Populate DB with sample data
    if(config.seedDB) { require('./config/seed'); }

    // Setup server
    var app = express();
    var server = require(config.protocol);

    if(config.env === 'production') {

      d.run(function(){
        server = server.createServer(config.sslOptions, app);
      });

      // Redirect from http port 80 to https
      var http = require('http');
      http.createServer(function (req, res) {
          res.writeHead(301, { "Location": "https://" + req.headers['host'] + req.url });
          res.end();
      }).listen(8080);
    } else{

      d.run (function (){
        server = server.createServer(app);
      });

    }

    app.use(session({
      genid: function(req) {
        return uuidFromBytes(crypto.randomBytes(16)) // use UUIDs for session IDs
      },
      secret: config.sessionSecret,
      resave: false,
      store: new redisStore({ host: config.redis.host, port: config.redis.port}),
      saveUninitialized: true
    }));

    require('./config/express')(app);
    require('./config/redis')();
    require('./routes')(app);

    if(!config.facebook.appId || !config.facebook.appSecret) {
        throw new Error('facebook appId and appSecret required in config.js');
    }

    // Start server
    server.listen(config.port, config.ip, function () {
      console.log('Express server listening on %d, in %s mode', config.port, app.get('env'));
    });

    var socketio_redis = require('socket.io-redis');

    var socketIO = require('socket.io')(server, {
        serveClient: (config.env === 'production') ? false : true,
        path: '/socket.io-client'
    });

    sub.subscribe('chat');

    socketIO.adapter(socketio_redis( {host: 'localhost', port: 6379}));

    socketIo.createSocketConnection(socketIO, sub, pub, store);

    // Expose app original
    exports = module.exports = app;
}

How can I modify the above code to make it work for chat application ?

Thanks

elad commented 8 years ago

Not an issue, closing...