1

Socket.io とクラスタリングを使用しています。私がする必要があるのは、複数の子プロセスを作成し、特定の [socket.io] ソケットをそれぞれに送信できるようにすることです。現在 (以下のコードを参照) [socket.io] ソケットをハンドルとして送信しようとすると、例外が発生します。

以下の私のコードにはそれがありません (最も基本的な例を機能させようとしているため) が、クライアントが接続できるようにして、メッセージに対してどのプロセスに進むかを伝えることです。したがって、クライアントはいくつかのデータを含む「init」メッセージを送信し、そのデータに基づいて [socket.io] ソケットを特定のプロセスに転送します。これが私の当初の計画でした。

すべての子プロセスから socket.io をリッスンできることはわかっていますが、クライアントが接続すると、それらのプロセスの 1 つだけが受信されます。

私の2つの質問は次のとおりです。

  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

このような方法でアプリケーションを構成しないでください。機能しないためです。クラスターは通常、高負荷を処理するために使用されます。負荷を分散したい場合は、クラスターと 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");
}

プロセスを送信するワーカーを実際に選択することはできないため、アプリケーションの再構築を検討する必要があります。1 つのワーカーが認証を使用してソケットを拒否した場合でも、クライアントは目的のワーカーを見つけるためにランダムに再接続し続ける必要があります。

異なるデータを受信するために異なるソケットが必要な場合は、ルームまたは名前空間を調べる必要があります。名前空間の仕組みは次のとおりです。

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 に答える