问题:是否可以对使用 Socket.io 提供 WebSocket 支持的应用程序进行集群?如果是这样,最好的实现方法是什么?
我构建了一个基于 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
是什么?如果它是 connect
附带的 MemoryStore
,则 session 不会在您的工作人员之间共享。每个工作人员都有自己的一组 session ,如果客户端连接到另一个工作人员,您将找不到他们的 session 。我建议你看一下例如connect-redis用于在进程之间共享 session 。基本用法:
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 等的模块。
但这只能解决您的部分问题,因为现在您在工作人员之间共享 session ,但是 socket.io
无法向连接到其他工作人员的客户端发送消息。基本上,如果您在一个工作线程中发出 socket.emit
,该消息只会发送到连接到同一工作线程的客户端。解决此问题的一种方法是使用 RedisStore
for socket.io
,它利用 Redis 在工作线程之间路由消息。基本用法:
var sio = require('socket.io')
, RedisStore = sio.RedisStore
, io = sio.listen(app);
io.set('store', new RedisStore);
现在,所有消息都应该路由到客户端,无论它们连接到哪个工作线程。
关于javascript - 集群 Node 应用程序时 Socket.io websocket 授权失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9245044/