集群节点应用程序时 Socket.io websocket 授权失败
问题:是否可以对使用 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
Question: Is it possible to cluster an application which is using Socket.io for WebSocket support? If so what would be the best method of implementation?
I've built an application which uses Express and Socket.io, built on Node.js. I'd like to incorporate clustering to increase the amount of requests that my application can process.
The following causes my application to produce a socket handshake error...
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);
}
A console log shows that socket.io is being started up multiple times.
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 is currently being set up in the top of my server code using:
var io = require('socket.io').listen(app);
The websocket authorization code:
//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);
}
});
Console log of the error message:
Error whilst authorizing websocket handshake
debug - authorized
warn - handshake error Error
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您的
sessionStore
是什么?如果它是connect
附带的MemoryStore
,则会话不会在您的工作人员之间共享。每个工作人员都有自己的一组会话,如果客户端连接到另一个工作人员,您将找不到他们的会话。我建议您查看 connect-redis 在进程之间共享会话。基本用法:当然,这需要你也设置好redis。在 Connect wiki 上有 CouchDB、memcached、postgres 等模块。
不过,这只能解决您的部分问题,因为现在您已经在工作人员之间共享了会话,但是
socket.io
无法向连接到其他工作人员的客户端发送消息。基本上,如果您在一个工作线程中发出socket.emit
,该消息只会发送到连接到同一工作线程的客户端。解决此问题的一种方法是使用RedisStore
forsocket.io
,它利用 Redis 在工作线程之间路由消息。基本用法:现在,所有消息都应该路由到客户端,无论它们连接到哪个工作线程。
另请参阅:Node.js、多线程和 Socket.io
What is your
sessionStore
? If it's theMemoryStore
shipped withconnect
, then sessions won't be shared between your workers. Each worker will have it's own set of sessions, and if a client connects to another worker, you wont find their session. I suggest you take a look at e.g. connect-redis for sharing sessions between processes. Basic usage:Of course, this requires that you also set up redis. Over at the Connect wiki there are modules for CouchDB, memcached, postgres and others.
This only solves part of your problem, though, because now you have sessions shared between workers, but
socket.io
has no way of sending messages to clients which are connected to other workers. Basically, if you issue asocket.emit
in one worker, that message will only be sent to clients connected to that same worker. One solution to this is to useRedisStore
forsocket.io
, which leverages redis to route messages between workers. Basic usage:Now, all messages should be routed to clients no matter what worker they are connected to.
See also: Node.js, multi-threading and Socket.io