如何处理哪个子进程获取socket.io套接字句柄

时间:2013-09-12 03:34:21

标签: javascript node.js socket.io

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

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

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

我的两个问题是:

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

  3. 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);
    

1 个答案:

答案 0 :(得分:2)

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

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

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);