Introducción
El módulo cluster
en Node.js permite la creación de procesos hijos que comparten el mismo puerto del servidor. Esto es útil para aprovechar al máximo los sistemas con múltiples núcleos de CPU, ya que Node.js es de un solo hilo por naturaleza. Al usar el módulo cluster
, puedes crear múltiples instancias de tu aplicación que se ejecutan en paralelo, mejorando así el rendimiento y la capacidad de respuesta.
Conceptos Clave
- Proceso Maestro (Master Process): El proceso principal que se encarga de crear y gestionar los procesos hijos (workers).
- Proceso Hijo (Worker Process): Procesos secundarios que ejecutan el código de la aplicación y manejan las solicitudes entrantes.
- Balanceo de Carga (Load Balancing): Distribuir las solicitudes entrantes entre los procesos hijos para optimizar el uso de recursos.
Ejemplo Práctico
Paso 1: Configuración del Proceso Maestro
Primero, necesitamos configurar el proceso maestro que creará y gestionará los procesos hijos.
const cluster = require('cluster'); const http = require('http'); const numCPUs = require('os').cpus().length; if (cluster.isMaster) { console.log(`Master ${process.pid} is running`); // Crear un worker por cada CPU disponible for (let i = 0; i < numCPUs; i++) { cluster.fork(); } cluster.on('exit', (worker, code, signal) => { console.log(`Worker ${worker.process.pid} died`); }); } else { // Los workers pueden compartir cualquier servidor TCP http.createServer((req, res) => { res.writeHead(200); res.end('Hello World\n'); }).listen(8000); console.log(`Worker ${process.pid} started`); }
Explicación del Código
-
Importar Módulos:
const cluster = require('cluster'); const http = require('http'); const numCPUs = require('os').cpus().length;
Importamos los módulos necesarios:
cluster
para la gestión de procesos,http
para crear el servidor yos
para obtener el número de CPUs disponibles. -
Proceso Maestro:
if (cluster.isMaster) { console.log(`Master ${process.pid} is running`);
Verificamos si el proceso actual es el maestro. Si es así, imprimimos un mensaje indicando que el proceso maestro está en ejecución.
-
Crear Workers:
for (let i = 0; i < numCPUs; i++) { cluster.fork(); }
Creamos un worker por cada CPU disponible utilizando
cluster.fork()
. -
Manejo de Eventos de Salida de Workers:
cluster.on('exit', (worker, code, signal) => { console.log(`Worker ${worker.process.pid} died`); });
Escuchamos el evento
exit
para detectar cuando un worker muere y registramos un mensaje en la consola. -
Proceso Worker:
} else { http.createServer((req, res) => { res.writeHead(200); res.end('Hello World\n'); }).listen(8000); console.log(`Worker ${process.pid} started`); }
Si el proceso no es el maestro, entonces es un worker. Creamos un servidor HTTP que responde con "Hello World" y lo ponemos a escuchar en el puerto 8000.
Ejercicio Práctico
Ejercicio 1: Crear un Servidor HTTP con Cluster
- Objetivo: Crear un servidor HTTP que maneje solicitudes de manera eficiente utilizando el módulo
cluster
. - Instrucciones:
- Configura un proceso maestro que cree un worker por cada CPU disponible.
- Cada worker debe manejar las solicitudes HTTP y responder con un mensaje personalizado.
- Implementa un manejo básico de errores para reiniciar los workers que mueran.
Solución
const cluster = require('cluster'); const http = require('http'); const numCPUs = require('os').cpus().length; if (cluster.isMaster) { console.log(`Master ${process.pid} is running`); for (let i = 0; i < numCPUs; i++) { cluster.fork(); } cluster.on('exit', (worker, code, signal) => { console.log(`Worker ${worker.process.pid} died. Restarting...`); cluster.fork(); }); } else { http.createServer((req, res) => { res.writeHead(200); res.end(`Hello from Worker ${process.pid}\n`); }).listen(8000); console.log(`Worker ${process.pid} started`); }
Explicación de la Solución
- Reinicio de Workers:
Cuando un worker muere, registramos un mensaje y creamos un nuevo worker para reemplazarlo.cluster.on('exit', (worker, code, signal) => { console.log(`Worker ${worker.process.pid} died. Restarting...`); cluster.fork(); });
Conclusión
El módulo cluster
es una herramienta poderosa para mejorar el rendimiento de las aplicaciones Node.js en sistemas con múltiples núcleos de CPU. Al distribuir las solicitudes entre varios procesos hijos, puedes manejar más tráfico y mejorar la capacidad de respuesta de tu aplicación. En el siguiente tema, exploraremos los hilos de trabajo (worker threads
) para tareas de computación intensiva.
Curso de Node.js
Módulo 1: Introducción a Node.js
Módulo 2: Conceptos Básicos
Módulo 3: Sistema de Archivos y E/S
Módulo 4: HTTP y Servidores Web
- Creando un Servidor HTTP Simple
- Manejo de Solicitudes y Respuestas
- Sirviendo Archivos Estáticos
- Enrutamiento
Módulo 5: NPM y Gestión de Paquetes
- Introducción a NPM
- Instalación y Uso de Paquetes
- Creación y Publicación de Paquetes
- Versionado Semántico
Módulo 6: Framework Express.js
- Introducción a Express.js
- Configuración de una Aplicación Express
- Middleware
- Enrutamiento en Express
- Manejo de Errores
Módulo 7: Bases de Datos y ORMs
- Introducción a las Bases de Datos
- Usando MongoDB con Mongoose
- Usando Bases de Datos SQL con Sequelize
- Operaciones CRUD
Módulo 8: Autenticación y Autorización
- Introducción a la Autenticación
- Usando Passport.js
- Autenticación JWT
- Control de Acceso Basado en Roles
Módulo 9: Pruebas y Depuración
- Introducción a las Pruebas
- Pruebas Unitarias con Mocha y Chai
- Pruebas de Integración
- Depuración de Aplicaciones Node.js
Módulo 10: Temas Avanzados
- Módulo Cluster
- Hilos de Trabajo
- Optimización del Rendimiento
- Construcción de APIs RESTful
- GraphQL con Node.js
Módulo 11: Despliegue y DevOps
- Variables de Entorno
- Usando PM2 para la Gestión de Procesos
- Desplegando en Heroku
- Integración y Despliegue Continuos