Skip to content

Commit

Permalink
#3 hice un pequeño refactor para los mapeos custom. además acomodé un…
Browse files Browse the repository at this point in the history
… poco el readme y agregué comentarios
  • Loading branch information
claudio-yuri committed Jul 1, 2017
1 parent 56cb731 commit bf33c79
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 44 deletions.
17 changes: 11 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ La solución cuenta con un proceso master que levanta tantos procesos workers co
### Load Balancer
Se corre con el comando
```bash
$ nodejs index.js # versión mono proceso
$ nodejs index.js # versión mono proceso [obsoleto]
$ nodejs cluster.js # versión multi proceso
```

Expand Down Expand Up @@ -55,12 +55,14 @@ Ahí vás a ver algo parecido a esto:
"serverExclusionTime": 10, //tiempo en segundos que se va a exlcuir a un servidor de la lista
//luego de ese tiempo, se lo volverá a considerar para enviarle requests
"maxRetryCount": 3, //cantidad de retries máximo por request
"debug": true, //define si muestra o no informaición en la consola
"debug": true, //define si muestra o no informaición en la consola. para mayor rendimiento se aconseja setear el valor en false
"cacheTimeout": 10, //duración de la información en caché
"serverList": [ //esta es la lista de servidores
"http://localhost:3100",
"http://localhost:3200",
"http://localhost:3300"
"http://localhost:3300",
"http://localhost:3400",
"http://localhost:3500"
],
"heartbeat":{
"executionInterval":10
Expand All @@ -75,13 +77,13 @@ Ahí vás a ver algo parecido a esto:
"servers": ["http://localhost:3100"]
},
{
"url": "*",
"url": "/heavytask",
"servers": ["http://localhost:3500"]
}
]
}
```
>observaciones: "url": "*" representa la opcion: en caso contario (default)
>observaciones: solo los patrones marcados en `requests` se atienden de manera especial, el resto cae en round robin
Luego, abrís varias consolas y vas levantando los mock server de la siguiente manera:

Expand All @@ -92,6 +94,10 @@ $ nodejs mock_server.js -p 3100
$ nodejs mock_server.js -p 3200
# consola 3
$ nodejs mock_server.js -p 3300
# consola 4
$ nodejs mock_server.js -p 3400
# consola 5
$ nodejs mock_server.js -p 3500
```
Finalmente, abrimos una consola más y levanamos el load balancer
``` bash
Expand All @@ -107,4 +113,3 @@ Ejemplo de prueba
# usamos '-l' porque el contenido es dinámico y si no lo usamos ab interpreta el reqeust como fallido
$ ab -n 1000 -c 100 -l http://localhost:3000/
```

30 changes: 8 additions & 22 deletions cluster.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,12 @@ if (cluster.isMaster) {
}
//cluster workers
else{
const srvMan = new ServerManager(config.serverList, config.serverExclusionTime);
const srvMan = new ServerManager(config.serverList, config.serverExclusionTime, config.requests);
var app = express();
const numberOfRetries = 3;

//todos los requests entrantes
app.all("/", (req, res) => {
app.all("*", (req, res) => {
console.info(`Recibí un request ${req.method} de ${req.ip}`);
console.debug(req.url);

Expand Down Expand Up @@ -94,28 +94,14 @@ else{
new ServerSupervisor(srvMan, config);
res.json({status: 'heartbeat ok'})
});

config.requests.forEach(function (request) {
srvMan.addServers(request.servers, request.url);
app.all(request.url, (req, res) => {
console.log(`Recibí un request ${req.method} de ${req.ip}`);
console.log(req.url);

getFromCache(req, res, ()=>{
//si no lo puede obtener de la cache

//determino la cantidad de retries disponibles según el tipo de request
var maxNumberOfRetries = config.maxRetryCount;
if (req.method === "POST" || req.method === "PUT" || req.method === "DELETE")
maxNumberOfRetries = 0;

//procedo a hacer el request
makeRequest(srvMan, req, res, process, maxNumberOfRetries);
});
});
});
}

/**
* Intenta obtener la información de caché en caso de ser necesario
* @param {Express.Request} req
* @param {Express.Response} res
* @param {function} callback La función a ser ejecutada en caso de un cache miss o cuando no se usa cache
*/
function getFromCache(req, res, callback) {

//si el request no puede usar cache
Expand Down
4 changes: 2 additions & 2 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"serverTimeout": 10,
"serverExclusionTime": 100000,
"maxRetryCount": 3,
"debug": false,
"debug": true,
"cacheTimeout": 10,
"serverList": [
"http://localhost:3100",
Expand All @@ -25,7 +25,7 @@
"servers": ["http://localhost:3100"]
},
{
"url": "*",
"url": "/heavytask",
"servers": ["http://localhost:3500"]
}
]
Expand Down
4 changes: 3 additions & 1 deletion modules/config-reader.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
//recibe la ruta del archivo de configuración
/**
* recibe la ruta del archivo de configuración
*/
module.exports = function(configFileName){
const fs = require('fs');

Expand Down
68 changes: 55 additions & 13 deletions modules/server-manager.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,25 @@
//esta clase se encarga de controlar el listado de servidores
//la idea es manejar la lista de servidores como una queue para lograr un comportamiento tipo round robin
/**
* esta clase se encarga de controlar el listado de servidores
* la idea es manejar la lista de servidores como una queue para lograr un comportamiento tipo round robin
*/
class ServerManager{
constructor(serverList, timeout){
/**
* Contructor del server manager
* @param {Array[String]} serverList La lista de servidores disponibles
* @param {Number} timeout segundos que tarda un server en volver a ser considerado online
* @param {Array[Object]} customRequests un mapeo de url => servidores para ruteos especiales
*/
constructor(serverList, timeout, customRequests){
this._serverList = serverList;
this._serverAltList = {};
//agrego los mapeos alternativos
if(customRequests.length > 0){
for(var pCR in customRequests){
this.addServers(customRequests[pCR].servers, customRequests[pCR].url);
}
}
this._serverStatus = {};
//por defecto todos los servers online
for (var pos in serverList){
this._serverStatus[serverList[pos]] = true;
}
Expand All @@ -13,30 +28,46 @@ class ServerManager{
this._nextPos = -1; //para que empiece en 0
this._nextPosAlt = -1;
}
getNext(pos, max){
/**
* Devuelve la posición del próximo server de la lista
* @param {number} pos
* @param {number} max
* @param {bool} useAltPos
*/
getNext(pos, max, useAltPos){
pos++; //round robin
if(pos >= max){
pos = 0;
}
if(useAltPos){
this._nextPosAlt = pos;
}
else{
this._nextPos = pos;
}
return pos;
}
/**
* Devuelve la url del servidor al que se va a hacer el request
* @param {string} url
*/
getServer(url){
var serverList, cont = 0, result = null, max, pos;
var serverList, cont = 0, result = null, max, pos, useAltPos = false;

//si hay una lista de servers para el request de url
if (this._serverAltList[url] != null){
serverList = this._serverAltList[url];
pos = this._nextPosAlt;
useAltPos = true;
}
else{
serverList = this._serverList;
pos = this._nextPos;
}

max = serverList.length;

while (cont < max){
pos = this.getNext(pos, max);
pos = this.getNext(pos, max, useAltPos);
if(this.isServerOnline(serverList[pos])){
result = serverList[pos];
break;
Expand All @@ -45,22 +76,33 @@ class ServerManager{
}
return result;
}
/**
* Agrega servidores con mapeo especial
* @param {Array} serverList
* @param {string} url
*/
addServers(serverList, url){
this._serverAltList[url] = serverList;
}
//devuelve true si el server está online
/**
* devuelve true si el server está online
* @param {string} host
*/
isServerOnline(host) {
return this._serverStatus[host];
}

//poner online un server
/**
* poner online un server
* @param {string} host
*/
setServerOnline(host){
// console.debug(host + " online");
this._serverStatus[host] = true;
}
//poner offline un server
/**
* poner offline un server
* @param {string} host
*/
setServerOffline(host){
// console.debug(host + " offline");
this._serverStatus[host] = false;
var _this = this;
setTimeout(function() {
Expand Down

0 comments on commit bf33c79

Please sign in to comment.