Hace poco aprendí sobre el módulo de cluster en el nodo y quería probarlo. Tengo una aplicación express súper básica que se ve así.
const express = require('express'); const app = express(); const cluster = require('cluster'); const os = require('os'); const numCores = os.cpus().length; app.get('/', (req, res) => { res.status(200).json({ success: true }) }); if (cluster.isMaster) { for (let i = 0; i < numCores; i++) { cluster.fork(); } cluster.on('exit', (worker, code, signal) => { console.log(`worker ${worker.process.pid} died`); console.log("Let's fork another worker!"); cluster.fork(); }); } else { app.listen(1337, () => console.log('server is running on port 1337')); }También estoy usando la herramienta de prueba de carga de artillería para probar esta aplicación de nodo básico.
El problema es que, ya sea que use el módulo de cluster o no, cuando termine de ejecutarse la prueba de carga, tengo la misma cantidad de solicitudes fallidas.
Este es el resultado de mi prueba.
Escenarios lanzados: 30000 Escenarios completados: 23145 Solicitudes completadas: 23145 Respuesta media/seg: 426,14 Tiempo de respuesta (mseg): min: 0 max: 449 mediana: 1 p95: 4 p99: 35 Recuento de escenarios: solicitud simple: 30000 (100 %) Códigos: 200: 23145 Errores: ETIMEDOUT: 6855
¿Por qué tengo errores 6855 ETIMEDOUT incluso cuando estoy usando el módulo de cluster ? Esta es exactamente la misma cantidad de errores que tengo cuando no uso el módulo de cluster .
Probablemente solo necesite definir el controlador dentro del niño:
const express = require('express'); const cluster = require('cluster'); const os = require('os'); const numCores = os.cpus().length; if (cluster.isMaster) { for (let i = 0; i < numCores; i++) { cluster.fork(); } cluster.on('exit', (worker, code, signal) => { console.log(`worker ${worker.process.pid} died`); console.log("Let's fork another worker!"); cluster.fork(); }); } else { const app = express(); app.get('/', (req, res) => { let result = -1; console.time(); for (let i = 0; i < 2 ** 28; i += 1) { result += i; } console.timeEnd(); res.status(200).json({ result }); }); app.listen(1337, () => console.log('server is running on port 1337')); } También pondría la const app = express() adentro.
Creo que definir el controlador antes de bifurcar causa el problema.
VER: Uso de un clúster en una aplicación Expressjs
Creo que la situación es que el cuello de botella de la implementación de su servidor no es la potencia de procesamiento, está en otro lugar como IO o memoria.
Si agrega algo de lógica en el controlador (consulte la secuencia de comandos actualizada anteriormente), cuando solo hay 1 trabajador, la utilización de la CPU se maximizará en aproximadamente un 25 % si tiene una máquina de cuatro núcleos.
No tengo artillería, así que uso el siguiente script para probar localmente.
const fetch = require('node-fetch'); const CONCURRENT_REQUEST = 8; let numberOfRequest = 100 - CONCURRENT_REQUEST; let failed = 0; const ping = () => ( fetch('http://localhost:1337') .then(r => r.json()) .then(({ success }) => { if (!success) { throw new Error('oops'); } }) .catch((e) => { // console.error(`index ${i}`, e); failed += 1; }) .then(() => { numberOfRequest -= 1; if (numberOfRequest > 0) { return ping(); } }) ); const requests = new Array(CONCURRENT_REQUEST).fill(0).map((_, i) => ( ping() )); Promise.all(requests).then(() => console.log('done. failed: ', failed));Con solo 1 trabajador:
Minutes : 1 Seconds : 1 Milliseconds : 199 TotalDays : 0.000708324185185185 TotalHours : 0.0169997804444444 TotalMinutes : 1.01998682666667 TotalSeconds : 61.1992096 TotalMilliseconds : 61199.2096Con 4 trabajadores:
Seconds : 17 Milliseconds : 249 Ticks : 172490478 TotalDays : 0.000199641756944444 TotalHours : 0.00479140216666667 TotalMinutes : 0.28748413 TotalSeconds : 17.2490478 TotalMilliseconds : 17249.0478