1

I build a sample code in node 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);

In this sample, I want to create proxy server inside cluster worker and this give me error bind EADDRINUSE null:800831 I want to know can I create http-proxy inside cluster worker. If I can't then there's solution for load balance between machines ?

1
  • Can't you use nginx or haproxy? Commented Nov 4, 2016 at 13:50

2 Answers 2

1

I create a proxy reverse exemple proxy reverse inside cluster and i create 3 servers in another files, it works for me (dont forget to run the servers separately for example on windows you launch servers in 4 cmd, 1 cmd for proxy and other (3 cmd) for servers )

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

}

Sign up to request clarification or add additional context in comments.

Comments

0

Ports should in 1-65535 range.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.