├── .gitignore ├── README.md ├── app.js ├── package.json └── public ├── index.html └── stylesheets └── style.css /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/* 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Scalable Socket.IO Sample 2 | ============= 3 | 4 | A minimal sample to demo the scalability of socket.io with node cluster, redis, and express. 5 | -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | var cluster = require('cluster') 2 | , numCPUs = require('os').cpus().length 3 | 4 | if (cluster.isMaster) { 5 | var worker, i; 6 | // Fork workers. 7 | for (i = 0; i < numCPUs; i++) { 8 | worker = cluster.fork(); 9 | console.info('Workerer #' + worker.id, 'with pid', worker.process.pid, 'is on'); 10 | } 11 | 12 | cluster.on('exit', function(worker, code, signal) { 13 | console.info('Workerer #' + worker.id, 'with pid', worker.process.pid, 'died'); 14 | }); 15 | 16 | } else { 17 | 18 | var express = require('express') 19 | , http = require('http') 20 | , path = require('path') 21 | , RedisStore = require('socket.io/lib/stores/redis') 22 | , redis = require('redis') 23 | , pub = redis.createClient() 24 | , sub = redis.createClient() 25 | , client = redis.createClient() 26 | , sio = require('socket.io'); 27 | 28 | var app = express(); 29 | var server 30 | , io; 31 | 32 | app.configure(function(){ 33 | var i = 0; 34 | app.set('port', process.env.PORT || 3000); 35 | app.use(function (req, res, next) { 36 | console.info('Worker #' + cluster.worker.id, 'is going to handle the request'); 37 | 38 | // do something to delay the worker 39 | while (i < 100000000) { 40 | i += 1; 41 | } 42 | 43 | next(); 44 | }); 45 | app.use(express.favicon()); 46 | app.use(express.logger('dev')); 47 | app.use(express.bodyParser()); 48 | app.use(express.methodOverride()); 49 | app.use(app.router); 50 | app.use(express.static(path.join(__dirname, 'public'))); 51 | }); 52 | 53 | app.configure('development', function(){ 54 | app.use(express.errorHandler()); 55 | }); 56 | 57 | server = http.createServer(app).listen(app.get('port'), function(){ 58 | console.info("Express server listening on port " + app.get('port')); 59 | }); 60 | 61 | /* Setup Socket.IO */ 62 | 63 | io = sio.listen(server); 64 | io.set('store', new RedisStore({ 65 | redisPub: pub 66 | , redisSub: sub 67 | , redisClient: client 68 | })); 69 | io.sockets.on('connection', function (socket) { 70 | var i = 0; 71 | 72 | // do something to delay the worker 73 | while (i < 100000000) { 74 | i += 1; 75 | } 76 | 77 | // create a private room for each client 78 | // use connect time as private room name 79 | // you might want to use the client's session id instead 80 | socket.join(Date.now()); 81 | 82 | // print out all rooms 83 | console.log('Worker #' + cluster.worker.id, 'receive a connection'); 84 | console.log('Current rooms:'); 85 | console.log(io.sockets.manager.rooms); 86 | 87 | socket.broadcast.emit('user connected'); 88 | }); 89 | 90 | /* End Setup Socket.IO */ 91 | 92 | } 93 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "application-name", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "start": "node app" 7 | }, 8 | "dependencies": { 9 | "express": "3.0.0rc4" 10 | , "socket.io": "*" 11 | , "redis": "*" 12 | , "connect-redis": "*" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |

Node: Socket.IO, Cluster, Redis, Express - All It Together

12 |

13 | Refresh the page quickly and you will see that the requests are passed to different workers. 14 |
15 | Or open new tabs to establish other connections with socket.io. 16 |

17 | 18 | 19 | -------------------------------------------------------------------------------- /public/stylesheets/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding: 50px; 3 | font: 14px "Lucida Grande", Helvetica, Arial, sans-serif; 4 | } 5 | 6 | a { 7 | color: #00B7FF; 8 | } --------------------------------------------------------------------------------