2017-08-06 13 views
3

私は複数のプロセスにまたがってsocket.ioを実行する方法を検討していました。Socket.io - 複数のノードを使用する

ここのガイド:https://socket.io/docs/using-multiple-nodes/は私にいくつかの質問を残しました。

これは、socket.ioプロセス間のロードバランスを設定するためのnginxの設定を使用していますが、以下のNode.jsに組み込まれているクラスタモジュールを使用しています。

これはNode.jsのnginxとクラスタモジュールを使用するはずですか?

また、ロードバランシングが機能しているかどうかを確認するにはどうすればよいですか。

私はredisアダプタを使用して実行している2つのsocket.ioプロセスとクラスタモジュールを使用してnginxオプションを使ってテストしました。

これは私が私のnginxの設定で持っていたものです:

http { 

     upstream io_nodes { 
     ip_hash; 
     server 127.0.0.1:6001; 
     server 127.0.0.1:6002; 
     } 

     server { 
     listen 3000; 
     server_name example.com; 
     location/{ 
     proxy_set_header Upgrade $http_upgrade; 
     proxy_set_header Connection "upgrade"; 
     proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 
     proxy_set_header Host $host; 
     proxy_http_version 1.1; 
     proxy_pass http://io_nodes; 
     } 
     } 

これは私のsocket.ioコード(そのほとんどはここから撮影:https://github.com/elad/node-cluster-socket.io):の一例である

var express = require('express'), 
    cluster = require('cluster'), 
    net = require('net'), 
    redis = require('redis'), 
    sio = require('socket.io'), 
    sio_redis = require('socket.io-redis'); 

var port = 6001, 
    num_processes = require('os').cpus().length; 

if (cluster.isMaster) { 
    console.log('is master 6001'); 
    // This stores our workers. We need to keep them to be able to reference 
    // them based on source IP address. It's also useful for auto-restart, 
    // for example. 
    var workers = []; 

    // Helper function for spawning worker at index 'i'. 
    var spawn = function(i) { 
     workers[i] = cluster.fork(); 

     // Optional: Restart worker on exit 
     workers[i].on('exit', function(code, signal) { 
      console.log('respawning worker', i); 
      spawn(i); 
     }); 
    }; 

    // Spawn workers. 
    for (var i = 0; i < num_processes; i++) { 
     spawn(i); 
    } 

    // Helper function for getting a worker index based on IP address. 
    // This is a hot path so it should be really fast. The way it works 
    // is by converting the IP address to a number by removing non numeric 
    // characters, then compressing it to the number of slots we have. 
    // 
    // Compared against "real" hashing (from the sticky-session code) and 
    // "real" IP number conversion, this function is on par in terms of 
    // worker index distribution only much faster. 
    var worker_index = function(ip, len) { 
     var s = ''; 
     for (var i = 0, _len = ip.length; i < _len; i++) { 
      if (!isNaN(ip[i])) { 
       s += ip[i]; 
      } 
     } 

     return Number(s) % len; 
    }; 

    // Create the outside facing server listening on our port. 
    var server = net.createServer({ pauseOnConnect: true }, function(connection) { 
     // We received a connection and need to pass it to the appropriate 
     // worker. Get the worker for this connection's source IP and pass 
     // it the connection. 
     var worker = workers[worker_index(connection.remoteAddress, num_processes)]; 
     worker.send('sticky-session:connection', connection); 
    }).listen(port); 
} else { 
    // Note we don't use a port here because the master listens on it for us. 
    var app = new express(); 

    // Here you might use middleware, attach routes, etc. 

    // Don't expose our internal server to the outside. 
    var server = app.listen(0, 'localhost'), 
     io = sio(server); 

    // Tell Socket.IO to use the redis adapter. By default, the redis 
    // server is assumed to be on localhost:6379. You don't have to 
    // specify them explicitly unless you want to change them. 
    io.adapter(sio_redis({ host: 'localhost', port: 6379 })); 

    // Here you might use Socket.IO middleware for authorization etc. 
     io.on('connection', function(socket) { 
     console.log('port 6001'); 
     console.log(socket.id); 
    }); 
    // Listen to messages sent from the master. Ignore everything else. 
    process.on('message', function(message, connection) { 
     if (message !== 'sticky-session:connection') { 
      return; 
     } 
     // Emulate a connection event on the server by emitting the 
     // event with the connection the master sent us. 
     server.emit('connection', connection); 

     connection.resume(); 
    }); 
} 

接続

正常に動作しているかどうかはどうすればわかりますか?クライアントが接続するたびに、ポート6001のsocket.ioプロセスに接続しているようです。

クライアント接続コードは、ポート3000に接続します。

+0

すべてのサーバープロセスが1台のコンピュータ上にある場合は、NGINXなしでクラスタモジュールを使用できます。複数のコンピュータを使用している場合は、NGINXのようなネットワークインフラストラクチャが必要です。また、両方のサーバーを併用することもできます(NGINXや各サーバー上でクラスタリングを実行するサーバーごとに複数のサーバーの負荷を分散します)。ここで重要な点は、node.jsのクラスタリングは同じホスト上の異なるプロセス間でのみ負荷を分散することです。 – jfriend00

+0

それは意味があります、ありがとうございます。私はちょうどそれすべてで混乱してしまった。 –

答えて

1

これはNode.jsのnginxとクラスタモジュールを使用するはずですか?

すべてのサーバープロセスが1台のコンピュータ上にある場合は、NGINXなしでクラスタモジュールを使用できます。

複数のサーバーコンピュータを使用している場合、node.jsクラスタリングではそれを行うことができないため、NGINXのようなネットワークインフラストラクチャが必要です。

また、両方のサーバーを組み合わせて使用​​することもできます(複数のサーバーは、NGINXや各サーバー上のクラスタリングを実行する各サーバーによって負荷分散されます)。ここで重要な点は、node.jsのクラスタリングは同じホスト上の異なるプロセス間でのみ負荷を分散することです。

また、ロードバランシングが機能しているかどうかを確認するにはどうすればよいですか。

各プロセスに処理中のアクティビティを記録させ、プロセスIDをロギングの一部として追加することができます。同時に複数のリクエストをサーバーにロードする場合は、各プロセス。実際の負荷テストを行う場合は、クラスタリングが有効で、クラスタリングを使用している場合と使用していない場合のスループットが大幅に向上するはずです。サーバーが実際にデータベースにバインドされていて、すべてのクラスタ化されたプロセスが同じデータベースを使用している場合、総スループットはボトルネックがどこにあるかによって異なりますので、node.jsプロセスをクラスタリングすることはあまり効果がありません。一方、node.jsプロセスが集中的に計算され、サーバーに複数のコアがある場合は、クラスタリングのメリットが得られます。

0

上記の溶液にさらにポイントを加える。

また、ロードバランシングが機能しているかどうかを確認するにはどうすればよいですか。

私は同じのためにノード・デバッグを使用しています、それは、スレッドの数あたりなど、複数のデバッガを開きます。ここで、ブレークポイントを追加して、負荷が適切に分散されているかどうかを確認できます。

関連する問題