Cómo escalar aplicaciones Node.js con clustering

Introducción

Node.js es un entorno de tiempo de ejecución de JavaScript del lado del servidor que se utiliza para crear aplicaciones web escalables y de alta velocidad. La escalabilidad es un factor crítico para cualquier aplicación web que pretenda manejar grandes volúmenes de tráfico. Una de las formas más populares de escalar aplicaciones Node.js es mediante el uso de clustering.

El clustering es una técnica que implica la creación de múltiples procesos Node.js que trabajan juntos para manejar la carga de la aplicación. Esto significa que cada solicitud que llega a la aplicación se distribuye en diferentes procesos para que puedan procesarse simultáneamente. También ayuda a garantizar que la aplicación sea tolerante a fallos y que siga funcionando incluso si uno de los procesos falla.

En este manual, se explicará cómo configurar el clustering y cómo escalar su aplicación Node.js con él.

Paso 1: Instalar Node.js

Antes de comenzar, asegúrate de tener Node.js instalado en tu sistema. Puedes descargarlo desde el sitio web oficial de Node.js e instalarlo en tu sistema.

Paso 2: Crear un archivo de aplicación Node.js

Crea un archivo de aplicación Node.js que escuche las solicitudes de los clientes. Este archivo será el punto de entrada para tu aplicación.

const http = require('http');
const server = http.createServer((req, res) => {
  res.end('Hello World!');
});
server.listen(3000);

Paso 3: Configurar dicha aplicación en modo cluster

Este es un ejemplo de una aplicación básica de Node.js que funciona en modo clúster:

// app.js

const cluster = require('cluster');
const http = require('http');
const numCPUs = require('os').cpus().length;

if (cluster.isMaster) {
  console.log(`Master process ID: ${process.pid}`);

  // Fork workers
  for (let i = 0; i < numCPUs; i++) {
    cluster.fork();
  }

  // Handle worker exit and restart
  cluster.on('exit', (worker, code, signal) => {
    console.log(`Worker process ID ${worker.process.pid} died`);
    console.log('Forking a new worker...');
    cluster.fork();
  });
} else {
  // Worker processes will enter this block
  // Create a simple HTTP server
  http.createServer((req, res) => {
    res.writeHead(200);
    res.end('Hello, world!\n');
  }).listen(3000);

  console.log(`Worker process ID ${process.pid} started`);
}

En este ejemplo, el proceso maestro es responsable de bifurcar los procesos de trabajo, mientras que los procesos de trabajo crean un servidor HTTP y manejan las solicitudes entrantes. Cada proceso de trabajo escucha en el mismo puerto (3000 en este caso), lo que les permite compartir el tráfico entrante.

Vamos a repasar cada parte del código y explicar su propósito:

const cluster = require('cluster');
const http = require('http');
const numCPUs = require('os').cpus().length;
  • El módulo cluster nos permite crear y gestionar un clúster de procesos trabajadores.
  • El módulo http proporciona funcionalidad para crear un servidor HTTP.
  • El módulo os se utiliza para determinar el número de núcleos de CPU disponibles en el sistema utilizando la propiedad cpus().length.
if (cluster.isMaster) {
  console.log(`ID del proceso maestro: ${process.pid}`);

  // Crear procesos trabajadores
  for (let i = 0; i < numCPUs; i++) {
    cluster.fork();
  }

  // Manejar la salida y reinicio de los procesos trabajadores
  cluster.on('exit', (worker, code, signal) => {
    console.log(`El proceso trabajador con ID ${worker.process.pid} ha finalizado`);
    console.log('Creando un nuevo proceso trabajador...');
    cluster.fork();
  });
} else {
  // Los procesos trabajadores entrarán en este bloque
  // Crear un servidor HTTP básico
  http.createServer((req, res) => {
    res.writeHead(200);
    res.end('¡Hola, mundo!\n');
  }).listen(3000);

  console.log(`El proceso trabajador con ID ${process.pid} ha comenzado`);
}
  • El bloque if (cluster.isMaster) se ejecuta solo en el proceso maestro. Comprueba si el proceso actual es el proceso maestro utilizando la propiedad isMaster del módulo cluster.
  • Si es el proceso maestro, imprime en la consola el ID del proceso maestro utilizando process.pid y luego procede a crear varios procesos trabajadores.
  • El bucle for crea los procesos trabajadores deseados (en este caso, numCPUs, que representa el número de núcleos de CPU).
  • El bloque cluster.on('exit', ...) se encarga de manejar la salida de los procesos trabajadores. Cada vez que un proceso trabajador termina (sale), se registra en la consola el ID del proceso trabajador y se crea un nuevo proceso trabajador para reemplazarlo.
  • Si el proceso actual no es el proceso maestro (es decir, es un proceso trabajador), entra en el bloque else.
  • Dentro del bloque else, cada proceso trabajador crea un servidor HTTP utilizando http.createServer() y escucha en el puerto 3000.
  • El servidor responde con un mensaje de "¡Hola, mundo!" para cada solicitud recibida.
  • El ID del proceso trabajador se muestra en la consola utilizando process.pid para indicar que el proceso trabajador ha comenzado.

Con esta configuración, el proceso maestro se encarga de gestionar los procesos workers. Los crea en base al número de núcleos de CPU disponibles y reinicia cualquier proceso worker que finalice. Los procesos workers manejan las solicitudes HTTP entrantes y les responden. Al distribuir la carga entre los procesos workers, la aplicación puede manejar más solicitudes concurrentes y mejorar el rendimiento.

Siéntete libre de modificar el código según tus requisitos y lógica de la aplicación.

Paso 4: Ejecutar la aplicación

  1. Guarda el código anterior en un archivo llamado app.js.

  2. Abre la terminal y navega hasta el directorio que contiene app.js.

  3. Inicia la aplicación usando el comando node:

    $ node app.js
    

Paso 5: Probar la aplicación

Prueba la aplicación abriendo un navegador web y escribiendo la dirección IP del servidor y el puerto en el que se está ejecutando la aplicación.

http://localhost:3000

Conclusión

El clustering es una técnica popular para escalar aplicaciones Node.js. Este manual ha demostrado cómo configurar y utilizar el clustering para distribuir la carga de la aplicación en múltiples procesos secundarios. Al seguir estos pasos, podrás escalar tu aplicación Node.js y hacerla más resistente a fallos.


2024 SW Hosting. Todos los derechos reservados. Los precios que aparecen en la web no incluyen impuestos