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:
You are accepting all the connections on master, won't this bottleneck the application in case the number of connections increases.
How can we use domains in your sample code ?
I'm using one more server which is listening on 8080 port(http) to rediect it to https. Should I create this server in my master process ?
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 ?
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:
How can I modify the above code to make it work for chat application ?
Thanks