Socket.io - 使用多个节点

Socket.io - using multiple nodes

所以我正在跨多个进程调查 运行 socket.io。

这里的指南:https://socket.io/docs/using-multiple-nodes/ 给我留下了一些问题。

它提到使用配置 nginx 来在 socket.io 个进程之间进行负载平衡,但它也在下面的 Node.js 中提到使用内置的集群模块。

我是否应该为此使用 Node.js 中的 nginx 和集群模块?

另外,如何判断负载平衡是否正常工作?

我使用带有两个 socket.io 进程 运行 的 nginx 选项使用 redis 适配器和集群模块对其进行了测试。

这是我的 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

Am I supposed to be using nginx AND the cluster module in Node.js for this?

如果您的所有服务器进程都在一台计算机上,则可以在没有 NGINX 的情况下使用集群模块。

如果您使用多台服务器计算机,那么您需要像 NGINX 这样的网络基础设施来在不同的服务器之间进行负载平衡,因为 node.js 集群无法为您做到这一点。

而且,您可以同时使用两者(多个服务器通过 NGINX 之类的东西进行负载平衡,每个服务器 运行 在每个服务器上集群)。这里的关键是 node.js 集群只在同一主机上的不同进程之间分散负载。

Also how do I tell if load balancing is working?

您可以让每个进程记录它正在处理的 activity 并将进程 ID 添加为日志记录的一部分,如果您同时向服务器加载多个请求,您应该会看到一些负载由每个进程处理。如果您进行实际负载测试,与不使用集群相比,当集群开启并工作时,您应该获得明显更高的吞吐量。请记住,总吞吐量取决于您的瓶颈所在,因此如果您的服务器实际上是数据库绑定的并且所有集群进程都使用相同的数据库,那么集群 node.js 进程可能不会给您带来太多好处。另一方面,如果您的 node.js 进程是计算密集型的,并且您的服务器中有多个内核,您可能会从集群中获得显着的好处。

为上述解决方案添加更多点。

Also how do I tell if load balancing is working?

我正在使用 node-debug,它根据线程数打开多个调试器。现在您可以添加断点来检查负载是否正确分配。