Node.js集群工作者内的http-proxy

时间:2016-08-18 10:24:24

标签: node.js node-http-proxy

我在节点js中构建了一个示例代码

var cluster = require("cluster"),
    http = require("http"),
    express = require('express'),
    port = parseInt(process.argv[2]||8001),
    servers =  ['http://127.0.0.1:800821', 'http://127.0.0.1:800831'];;

if (cluster.isMaster) {

  console.log('Master ' + process.pid + ' has started.');
     var numWorkers = require('os').cpus().length;

    console.log('Master cluster setting up ' + numWorkers + ' workers...');

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

    cluster.on('online', function(worker) {
        console.log('Worker ' + worker.process.pid + ' is online');
    });

    cluster.on('exit', function(worker, code, signal) {
        console.log('Worker ' + worker.process.pid + ' died with code: ' + code + ', and signal: ' + signal);
        console.log('Starting a new worker');
        cluster.fork();
    });
} else {
    var httpProxy = require('http-proxy');
    var proxy = httpProxy.createProxyServer();
    var count = 0;
    // Workers share the TCP connection in this server
    var app = express();
    app.get('/', function (req, res) {
        console.log('Cluster => ' + process.pid);
        loadBalanceProxy(req,res);
    }).listen(port);

    var currentServer = 1;
    function loadBalanceProxy(req, res){
        var cur = currentServer%servers.length;
        currentServer++;
        var target = servers[cur];
        console.log("Proxy => " + target);
        proxy.web(req, res, {
            target: target
        });
    }
}

http.createServer(function (req, res) {
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.write('request successfully proxied to: ' + req.url + '\n' + JSON.stringify(req.headers, true, 2));
  res.end();
}).listen(800831);

http.createServer(function (req, res) {
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.write('request successfully proxied to: ' + req.url + '\n' + JSON.stringify(req.headers, true, 2));
  res.end();
}).listen(800821);

在此示例中,我想在群集工作器中创建代理服务器,这会给我错误bind EADDRINUSE null:800831 我想知道我可以在集群工作者中创建http-proxy。如果我不能解决机器之间的负载平衡问题呢?

1 个答案:

答案 0 :(得分:0)

我在群集内部创建了一个代理反向exemple proxy reverse,我在另一个文件中创建了3个服务器,它适用于我(不要忘记单独运行服务器,例如在启动4 cmd服务器的窗口上,1 cmd for代理和其他(3厘米)的服务器)

// var https = require('https'); scure
var http = require('http');
var proxy = require('http-proxy');

var cluster = require('cluster');

var fs = require('fs');
var request = require('request');
// const numCPUs = require('os').cpus().length;
var numCPUs = 4;

if (cluster.isMaster) {

  for (var i = 0; i < numCPUs; i++) {

    cluster.fork();

  }
  cluster.on('fork', (worker) => {
    console.log('worker  ' + worker.process.pid);
  });

  cluster.on('exit', function(worker, code, signal) {
    console.log('Worker ' + worker.process.pid + ' died with code: ' + code + ', and signal: ' + signal);
    console.log('Starting a new worker');
    cluster.fork();
  });

} else {
  startProxyReverse();

}

function startProxyReverse() {

  http.globalAgent.maxSockets = 10240;

  // Define the servers to load balance.
  var servers = [{
    host: '127.0.0.1',
    port: 8001
  }, {
    host: '127.0.0.1',
    port: 8003
  }, {
    host: '127.0.0.1',
    port: 8002
  }];
  var failoverTimer = [];

  // load the SSL cert
  // var ca = [
  // fs.readFileSync('./certs/PositiveSSLCA2.crt'),
  // fs.readFileSync('./certs/AddTrustExternalCARoot.crt')
  // ];
  // var opts = {
  // ca : ca,
  // key : fs.readFileSync('./certs/example_wild.key'),
  // cert : fs.readFileSync('./certs/STAR_example_com.crt')
  // };

  // Create a proxy object for each target.
  var proxies = servers.map(function(target) {
    return new proxy.createProxyServer({
      target: target
        // ws : true,
        // xfwd : true,
        // ssl : opts,
        // down : false
    });
  });

  /**
   * Select a random server to proxy to. If a 'server' cookie is set, use that
   * as the sticky session so the user stays on the same server (good for ws fallbacks).
   * @param  {Object} req HTTP request data
   * @param  {Object} res HTTP response
   * @return {Number}     Index of the proxy to use.
   */
  var selectServer = function(req, res) {
    var index = -1;
    var i = 0;

    // Check if there are any cookies.
    if (req.headers && req.headers.cookie && req.headers.cookie.length > 1) {
      var cookies = req.headers.cookie.split('; ');

      for (i = 0; i < cookies.length; i++) {
        if (cookies[i].indexOf('server=') === 0) {
          var value = cookies[i].substring(7, cookies[i].length);
          if (value && value !== '') {
            index = value;
            break;
          }
        }
      }
    }

    // Select a random server if they don't have a sticky session.
    if (index < 0 || !proxies[index]) {
      index = Math.floor(Math.random() * proxies.length);
    }

    // If the selected server is down, select one that isn't down.
    if (proxies[index].options.down) {
      index = -1;

      var tries = 0;
      while (tries < 5 && index < 0) {
        var randIndex = Math.floor(Math.random() * proxies.length);
        if (!proxies[randIndex].options.down) {
          index = randIndex;
        }

        tries++;
      }
    }

    index = index >= 0 ? index : 0;

    // Store the server index as a sticky session.
    if (res) {
      res.setHeader('Set-Cookie', 'server=' + index + '; path=/');
    }

    return index;
  };

  /**
   * Fired when there is an error with a request.
   * Sets up a 10-second interval to ping the host until it is back online.
   * There is a 10-second buffer before requests start getting blocked to this host.
   * @param  {Number} index Index in the proxies array.
   */
  var startFailoverTimer = function(index) {
    if (failoverTimer[index]) {
      return;
    }

    failoverTimer[index] = setTimeout(function() {
      // Check if the server is up or not
      request({
        url: 'http://' + proxies[index].options.target.host + ':' + proxies[index].options.target.port,
        method: 'HEAD',
        timeout: 10000
      }, function(err, res, body) {
        failoverTimer[index] = null;

        if (res && res.statusCode === 200) {
          proxies[index].options.down = false;
          console.log('Server #' + index + ' is back up.');
        } else {
          proxies[index].options.down = true;
          startFailoverTimer(index);
          console.log('Server #' + index + ' is still down.');
        }
      });
    }, 10000);
  };

  // Select the next server and send the http request.
  var serverCallback = function(req, res) {
    console.log('Process ' + process.pid + ' is listening to all incoming requests');
    var proxyIndex = selectServer(req, res);
    console.log(proxyIndex);
    var proxy = proxies[proxyIndex];
    proxy.web(req, res);

    proxy.on('error', function(err) {
      startFailoverTimer(proxyIndex);
    });
  };
  console.log('create server');
  // var server = http.createServer(opts, serverCallback); scure server
  var server = http.createServer(serverCallback);
  // http.createServer(serverCallback).listen(8000);


  // Get the next server and send the upgrade request.
  // server.on('upgrade', function (req, socket, head) {
  // var proxyIndex = selectServer(req);
  // var proxy = proxies[proxyIndex];
  // proxy.ws(req, socket, head);

  // proxy.on('error', function (err, req, socket) {
  // socket.end();
  // startFailoverTimer(proxyIndex);
  // });
  // });
  server.listen(8000);
  // server.listen(443); scure port
  // var proxi = proxy.createServer();

  // http.createServer(function (req, res) {

  // var target = {
  // target : servers.shift()
  // };
  // console.log('Process ' + process.pid + ' is listening to all incoming requests');

  // console.log('balancing request to: ', target);
  // proxi.web(req, res, target);


  // servers.push(target.target);
  // }).listen(8000);

}