1

我正在使用 Socket.io 和集群。我需要做的是能够创建多个子进程并根据我认为合适的方式向每个子进程发送特定的 [socket.io] 套接字。目前(参见下面的代码)当我尝试将 [socket.io] 套接字作为句柄发送时,我得到一个异常。

我下面的代码没有它(因为我试图让最基本的示例工作)但我想要做的是允许客户端连接并告诉它在某些消息上要执行什么过程。因此,客户端将发送带有一些数据的“init”消息,并基于该数据将 [socket.io] 套接字转发到特定进程。这是我最初的计划。

我知道我可以让 socket.io 从每个子进程中侦听,但是当客户端连接时,只有其中一个进程会接收到它。

我的两个问题是:

  1. 有没有办法将 socket.io 套接字发送到子进程?
  2. 如果没有,是否有另一种方法来决定哪个进程获得句柄?(您能否在每个进程中使用不同的授权功能,如果一个进程不接受另一个进程可以接受的套接字?)

var cluster = require('cluster');

if (cluster.isMaster) {
    var io = require('socket.io').listen(80);
    var cpuCount = require('os').cpus().length;
    var children = [];

    for (var i = 0; i < cpuCount; i += 1) {
        children.push(cluster.fork());
    }

    //Master Process is listening for all connections
    io.sockets.on('connection', function (socket) {

        //upon a connection, send the 'handle' to a worker.
        children[0].send('server', socket);
    });
} else {
    process.on('message', function (m, handle) {
        //worker receives it here.
        console.log('here');
    });
}

带有堆栈跟踪的控制台输出:

C:\Users\randy>node "C:\Users\randy\Documents\Visual Studio 2012\Projects\tesselconnect-server\tesselconnect-server\server.js"
   info  - socket.io started
   debug - client authorized
   info  - handshake authorized bZCM2CVpFFdU9eU1zYwx
   debug - setting request GET /socket.io/1/websocket/bZCM2CVpFFdU9eU1zYwx
   debug - set heartbeat interval for client bZCM2CVpFFdU9eU1zYwx
   debug - client authorized for
   debug - websocket writing 1::

child_process.js:427
        throw new TypeError("This handle type can't be sent");
              ^
TypeError: This handle type can't be sent
    at ChildProcess.target.send (child_process.js:427:15)
    at Worker.send (cluster.js:401:21)
    at SocketNamespace.<anonymous> (C:\Users\randy\Documents\Visual Studio 2012\Projects\tesselconnect-server\tesselconnect-server\server.js:16:15)
    at SocketNamespace.EventEmitter.emit [as $emit] (events.js:117:20)
    at connect (C:\Users\randy\node_modules\socket.io\lib\namespace.js:292:10)
    at C:\Users\randy\node_modules\socket.io\lib\namespace.js:308:13
    at SocketNamespace.authorize (C:\Users\randy\node_modules\socket.io\lib\namespace.js:252:5)
    at SocketNamespace.handlePacket (C:\Users\randy\node_modules\socket.io\lib\namespace.js:302:14)
    at Manager.handleClient (C:\Users\randy\node_modules\socket.io\lib\manager.js:698:32)
    at Manager.handleUpgrade (C:\Users\randy\node_modules\socket.io\lib\manager.js:618:8)

第 16 行:

children[0].send('server', socket);
4

1 回答 1

3

您不应该以这种方式构建您的应用程序,因为它不起作用。Cluster 通常用于处理高负载,如果您想分散负载,则可以使用 Cluster 和 Redis 存储。

除此之外,您不能将 Socket.IO 套接字对象发送给工作人员,因为它将无法通过此检查:

if (handle instanceof net.Socket) {
  message.type = 'net.Socket';
} else if (handle instanceof net.Server) {
  message.type = 'net.Server';
} else if (handle instanceof process.binding('tcp_wrap').TCP ||
           handle instanceof process.binding('pipe_wrap').Pipe) {
  message.type = 'net.Native';
} else if (handle instanceof dgram.Socket) {
  message.type = 'dgram.Socket';
} else if (handle instanceof process.binding('udp_wrap').UDP) {
  message.type = 'dgram.Native';
} else {
  throw new TypeError("This handle type can't be sent");
}

您无法真正选择将流程发送给哪个工作人员,因此您应该考虑重组您的应用程序。即使一个工作人员使用身份验证拒绝了一个套接字,客户端也必须保持随机重新连接以找到其预期的工作人员。

如果您需要不同的套接字来接收不同的数据,您应该查看房间或名称空间。这就是命名空间的工作原理:

var nsp = io.of('/nsp');

nsp.on('connection', function(socket) {
  // use socket here as you would with the global namespace
});

这就是房间的工作方式:

io.sockets.on('connection', function(socket) {
  socket.join('room');
});

// emit to clients in that room
io.sockets.in('room').emit('event_name', data);
于 2013-09-12T04:07:55.380 回答