javascript - 集群 Node 应用程序时 Socket.io websocket 授权失败

标签 javascript node.js socket.io cluster-computing

问题:是否可以对使用 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);

现在,所有消息都应该路由到客户端,无论它们连接到哪个工作线程。

另请参阅:Node.js, multi-threading and Socket.io

关于javascript - 集群 Node 应用程序时 Socket.io websocket 授权失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9245044/

相关文章:

JavaScript/jQuery 输入[type=text] 模式

javascript - 向玩家添加统计数据+重叠方法

javascript - jQuery UI 按钮集禁用构造函数选项不起作用

javascript - 使用 "fs"读取 JSON 文件会抛出 "invalid json"Node.js

node.js - Webpack2 热模块重新加载 Express.js 通用 React 应用程序

node.js - Socket.io 不适用于 Firefox 和 Chrome

JavaScript 变量更新

javascript - Webpack:ReferenceError:文档未定义

node.js - SPA 中的公共(public)和私有(private) socket.io 连接

android - 客户端 Android Phonegap 应用程序的实时状态更新