集群节点应用程序时,Socket.io websocket授权失败

问题:是否可以将使用Socket.io进行WebSocket支持的应用程序集群化? 如果是的话,那么最好的实施方法是什么?

我已经构build了一个应用程序,它使用基于Node.js的Express和Socket.io。 我想包含集群来增加我的应用程序可以处理的请求数量。

以下原因导致我的应用程序产生套接字握手错误…

var cluster = require('cluster'); var numCPUs = require('os').cpus().length; if (cluster.isMaster) { // Fork workers. for (var i = 0; i < numCPUs; i++) { cluster.fork(); } cluster.on('death', function(worker) { console.log('worker ' + worker.pid + ' died'); }); } else { app.listen(3000); } 

控制台日志显示socket.io正在多次启动。

 jack@jack:~$ node nimble/app.js info - socket.io started info - socket.io started info - socket.io started info - socket.io started info - socket.io started info - socket.io started info - socket.io started info - socket.io started info - socket.io started 

Socket.io目前正在我的服务器代码的顶部使用:

 var io = require('socket.io').listen(app); 

websocket授权码:

 //Auth the user io.set('authorization', function (data, accept) { // check if there's a cookie header if (data.headers.cookie) { data.cookie = parseCookie(data.headers.cookie); data.sessionID = data.cookie['express.sid']; //Save the session store to the data object data.sessionStore = sessionStore; sessionStore.get(data.sessionID, function(err, session){ if(err) throw err; if(!session) { console.error("Error whilst authorizing websocket handshake"); accept('Error', false); } else { console.log("AUTH USERNAME: " + session.username); if(session.username){ data.session = new Session(data, session); accept(null, true); }else { accept('Invalid User', false); } } }) } else { console.error("No cookie was found whilst authorizing websocket handshake"); return accept('No cookie transmitted.', false); } }); 

控制台日志中的错误消息:

 Error whilst authorizing websocket handshake debug - authorized warn - handshake error Error 

什么是你的sessionStore ? 如果是connectMemoryStore ,则会话将不会在您的工作人员之间共享。 每个工作人员将拥有自己的会话集,如果客户端连接到另一个工作人员,则不会find他们的会话。 我build议你看看例如connect-redis在进程之间共享会话。 基本用法:

 var connect = require('connect') , RedisStore = require('connect-redis')(connect); var app = connect.createServer(); app.use(connect.session({store: new RedisStore, secret: 'top secret'}); 

当然,这也要求你也设置redis。 在Connect wiki上,有CouchDB,memcached,postgres等模块。

但是,这只能解决你的部分问题,因为现在你有工作人员之间共享的会话,但是socket.io没有办法向连接到其他工作者的客户端发送消息。 基本上,如果你在一个worker中发出一个socket.emit ,这个消息只会被发送给连接到同一个worker的客户端。 对此的一个解决scheme是使用RedisStore for socket.io ,它利用redis在工作人员之间路由消息。 基本用法:

 var sio = require('socket.io') , RedisStore = sio.RedisStore , io = sio.listen(app); io.set('store', new RedisStore); 

现在,所有的消息都应该被路由到客户端,不pipe他们连接的是什么工作者。

另请参见: Node.js,multithreading和Socket.io