kukuy 1.5.0 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/README.md +159 -188
  2. package/balancer.log +30 -0
  3. package/certs/auto/certificate.crt +22 -0
  4. package/certs/auto/private.key +28 -0
  5. package/kukuy-plugins/README.md +125 -0
  6. package/kukuy-plugins/cache-plugin/index.js +477 -0
  7. package/kukuy-plugins/cache-plugin/manifest.json +17 -0
  8. package/kukuy-plugins/ejemplo-plugin/index.js +41 -0
  9. package/kukuy-plugins/ejemplo-plugin/manifest.json +11 -0
  10. package/kukuy-plugins/health-checker/index.js +168 -0
  11. package/kukuy-plugins/health-checker/manifest.json +16 -0
  12. package/kukuy-plugins/health-monitor/index.js +58 -0
  13. package/kukuy-plugins/health-monitor/manifest.json +16 -0
  14. package/kukuy-plugins/redirect-plugin/index.js +172 -0
  15. package/kukuy-plugins/redirect-plugin/manifest.json +15 -0
  16. package/package.json +7 -3
  17. package/servers_real.json +5 -0
  18. package/src/core/Balancer.js +176 -39
  19. package/src/core/ServerPool.js +2 -2
  20. package/src/extensibility/ExtendedFilterChain.js +90 -0
  21. package/src/extensibility/ExtendedHookManager.js +87 -0
  22. package/src/extensibility/FilterChain.js +2 -9
  23. package/src/extensibility/HookManager.js +1 -0
  24. package/src/extensibility/PostStartupExtension.js +97 -0
  25. package/src/plugins/PluginManager.js +231 -0
  26. package/src/utils/HealthChecker.js +61 -6
  27. package/.ctagsd/ctagsd.json +0 -954
  28. package/.ctagsd/file_list.txt +0 -100
  29. package/.ctagsd/tags.db +0 -0
  30. package/CHANGELOG.md +0 -125
  31. package/LICENSE +0 -680
  32. package/README-SSL.md +0 -165
  33. package/captura.png +0 -0
  34. package/kukuu1.webp +0 -0
  35. package/kukuy.workspace +0 -11
  36. package/optimize-mariadb.sh +0 -152
  37. package/restart-balancer.sh +0 -10
  38. package/scripts/load_test.py +0 -151
  39. package/stress-test.js +0 -190
  40. package/test_optimization.js +0 -54
@@ -0,0 +1,168 @@
1
+ const http = require('http');
2
+ const https = require('https');
3
+ const url = require('url');
4
+
5
+ let healthCheckIntervalId = null;
6
+
7
+ async function init(balancer) {
8
+ console.log('Inicializando plugin de verificación de salud periódica...');
9
+
10
+ const config = balancer.config;
11
+ const healthCheckInterval = config.healthCheckInterval || 30000; // 30 segundos por defecto
12
+ const serverPool = balancer.serverPool;
13
+
14
+ // Función para verificar la salud de un servidor
15
+ async function checkServerHealth(server) {
16
+ try {
17
+ const parsedUrl = url.parse(server.url);
18
+ const options = {
19
+ hostname: parsedUrl.hostname,
20
+ port: parsedUrl.port,
21
+ path: '/health', // Ruta estándar para verificación de salud
22
+ method: 'GET',
23
+ timeout: 5000, // 5 segundos de timeout
24
+ // Agregar headers para identificar la solicitud de health check
25
+ headers: {
26
+ 'User-Agent': 'Kukuy-Health-Check/1.0'
27
+ }
28
+ };
29
+
30
+ // Emitir hook antes de realizar el check
31
+ await executeHook(balancer, 'onHealthCheckStart', { server, checkTime: new Date() });
32
+
33
+ return new Promise((resolve) => {
34
+ const request = server.protocol === 'https:'
35
+ ? https.request(options)
36
+ : http.request(options);
37
+
38
+ request.on('response', (res) => {
39
+ // Consumir el cuerpo de la respuesta para liberar recursos
40
+ res.resume();
41
+
42
+ // Considerar saludable si obtenemos una respuesta exitosa
43
+ const isHealthy = res.statusCode >= 200 && res.statusCode < 400;
44
+
45
+ // Actualizar estado del servidor
46
+ server.healthy = isHealthy;
47
+ server.lastChecked = Date.now();
48
+
49
+ // Emitir hook después de completar el check
50
+ executeHook(balancer, 'onHealthCheckComplete', {
51
+ server,
52
+ isHealthy,
53
+ statusCode: res.statusCode,
54
+ checkTime: new Date()
55
+ }).then(() => {
56
+ // Resolver la promesa después de emitir el hook
57
+ resolve(isHealthy);
58
+ }).catch(() => {
59
+ // En caso de error al emitir el hook, resolver igualmente
60
+ resolve(isHealthy);
61
+ });
62
+ });
63
+
64
+ request.on('error', (err) => {
65
+ // Actualizar estado del servidor
66
+ server.healthy = false;
67
+ server.lastChecked = Date.now();
68
+
69
+ // Emitir hook cuando ocurre un error en el check
70
+ executeHook(balancer, 'onHealthCheckError', {
71
+ server,
72
+ error: err,
73
+ checkTime: new Date()
74
+ }).then(() => {
75
+ resolve(false);
76
+ }).catch(() => {
77
+ resolve(false);
78
+ });
79
+ });
80
+
81
+ request.on('timeout', () => {
82
+ // Actualizar estado del servidor
83
+ server.healthy = false;
84
+ server.lastChecked = Date.now();
85
+
86
+ // Emitir hook cuando ocurre un timeout en el check
87
+ executeHook(balancer, 'onHealthCheckTimeout', {
88
+ server,
89
+ checkTime: new Date()
90
+ }).then(() => {
91
+ resolve(false);
92
+ }).catch(() => {
93
+ resolve(false);
94
+ });
95
+ });
96
+
97
+ request.end();
98
+ });
99
+ } catch (error) {
100
+ // Emitir hook cuando ocurre una excepción
101
+ await executeHook(balancer, 'onHealthCheckException', {
102
+ server,
103
+ error,
104
+ checkTime: new Date()
105
+ });
106
+
107
+ // Actualizar estado del servidor
108
+ server.healthy = false;
109
+ server.lastChecked = Date.now();
110
+
111
+ return false;
112
+ }
113
+ }
114
+
115
+ // Función para verificar la salud de todos los servidores
116
+ async function checkAllServersHealth() {
117
+ console.log('[HEALTH-CHECKER] Iniciando verificación de salud periódica...');
118
+
119
+ const servers = serverPool.getServers();
120
+
121
+ for (const server of servers) {
122
+ console.log(`[HEALTH-CHECKER] Verificando salud de ${server.url}...`);
123
+ await checkServerHealth(server);
124
+ }
125
+
126
+ // Invalidar la caché de servidores saludables después de la verificación
127
+ serverPool.invalidateCache();
128
+
129
+ console.log('[HEALTH-CHECKER] Verificación de salud periódica completada.');
130
+ }
131
+
132
+ // Iniciar verificación de salud periódica
133
+ healthCheckIntervalId = setInterval(checkAllServersHealth, healthCheckInterval);
134
+
135
+ console.log(`[HEALTH-CHECKER] Verificación de salud periódica iniciada. Intervalo: ${healthCheckInterval}ms`);
136
+
137
+ // Realizar una verificación inmediata
138
+ await checkAllServersHealth();
139
+ }
140
+
141
+ async function deinit(balancer) {
142
+ console.log('Desactivando plugin de verificación de salud periódica...');
143
+
144
+ // Detener la verificación de salud periódica
145
+ if (healthCheckIntervalId) {
146
+ clearInterval(healthCheckIntervalId);
147
+ healthCheckIntervalId = null;
148
+ console.log('[HEALTH-CHECKER] Verificación de salud periódica detenida.');
149
+ }
150
+ }
151
+
152
+ /**
153
+ * Execute a hook if the balancer reference is available
154
+ * @param {Object} balancer - Reference to the balancer
155
+ * @param {string} hookName - Name of the hook to execute
156
+ * @param {Object} data - Data to pass to the hook
157
+ */
158
+ async function executeHook(balancer, hookName, data) {
159
+ if (balancer && balancer.hookManager) {
160
+ try {
161
+ await balancer.hookManager.executeHooks(hookName, data);
162
+ } catch (error) {
163
+ console.error(`Error executing ${hookName} hook:`, error);
164
+ }
165
+ }
166
+ }
167
+
168
+ module.exports = { init, deinit };
@@ -0,0 +1,16 @@
1
+ {
2
+ "name": "Verificador de Salud Periódica",
3
+ "version": "1.0.0",
4
+ "description": "Plugin para verificar periódicamente la salud de los servidores backend",
5
+ "author": "Sistema Kukuy",
6
+ "main": "index.js",
7
+ "kukuyVersion": "^1.6.0",
8
+ "hooks": [
9
+ "onHealthCheckStart",
10
+ "onHealthCheckComplete",
11
+ "onHealthCheckError",
12
+ "onHealthCheckTimeout",
13
+ "onHealthCheckException"
14
+ ],
15
+ "enabled": true
16
+ }
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Plugin de Monitor de Salud de Servidores para Kukuy
3
+ * Monitorea eventos de verificación de salud de servidores backend
4
+ */
5
+
6
+ async function init(balancer) {
7
+ console.log('Inicializando plugin de monitor de salud de servidores...');
8
+
9
+ const extension = balancer.getPostStartupExtension();
10
+
11
+ // Hook que se ejecuta cuando comienza la verificación de salud de un servidor
12
+ extension.registerHook('onHealthCheckStart', async ({ server, checkTime }) => {
13
+ console.log(`[HEALTH-MONITOR] Iniciando verificación de salud para servidor: ${server.url} (${checkTime})`);
14
+ }, 5);
15
+
16
+ // Hook que se ejecuta cuando se completa la verificación de salud
17
+ extension.registerHook('onHealthCheckComplete', async ({ server, isHealthy, statusCode, checkTime }) => {
18
+ const status = isHealthy ? 'SALUDABLE' : 'NO SALUDABLE';
19
+ console.log(`[HEALTH-MONITOR] Verificación completada para ${server.url} - Estado: ${status} - Código: ${statusCode} (${checkTime})`);
20
+
21
+ // Aquí podrías agregar lógica adicional como alertas o métricas personalizadas
22
+ if (!isHealthy) {
23
+ console.warn(`[HEALTH-MONITOR] ¡Alerta! Servidor ${server.url} no está saludable`);
24
+ }
25
+ }, 5);
26
+
27
+ // Hook que se ejecuta cuando ocurre un error durante la verificación de salud
28
+ extension.registerHook('onHealthCheckError', async ({ server, error, checkTime }) => {
29
+ console.error(`[HEALTH-MONITOR] Error en verificación de salud para ${server.url}: ${error.message} (${checkTime})`);
30
+
31
+ // Lógica para manejar errores de verificación
32
+ console.warn(`[HEALTH-MONITOR] ¡Error crítico! Servidor ${server.url} no pudo ser verificado`);
33
+ }, 10); // Prioridad alta para errores
34
+
35
+ // Hook que se ejecuta cuando ocurre un timeout durante la verificación de salud
36
+ extension.registerHook('onHealthCheckTimeout', async ({ server, checkTime }) => {
37
+ console.warn(`[HEALTH-MONITOR] Timeout en verificación de salud para ${server.url} (${checkTime})`);
38
+
39
+ // Lógica para manejar timeouts
40
+ console.warn(`[HEALTH-MONITOR] ¡Timeout! Servidor ${server.url} no respondió a tiempo`);
41
+ }, 10); // Prioridad alta para timeouts
42
+
43
+ // Hook que se ejecuta cuando ocurre una excepción durante la verificación de salud
44
+ extension.registerHook('onHealthCheckException', async ({ server, error, checkTime }) => {
45
+ console.error(`[HEALTH-MONITOR] Excepción en verificación de salud para ${server.url}: ${error.message} (${checkTime})`);
46
+
47
+ // Lógica para manejar excepciones
48
+ console.error(`[HEALTH-MONITOR] ¡Excepción crítica! Error inesperado verificando ${server.url}`);
49
+ }, 10); // Prioridad alta para excepciones
50
+
51
+ console.log('Plugin de monitor de salud de servidores inicializado correctamente');
52
+ }
53
+
54
+ async function deinit(balancer) {
55
+ console.log('Desactivando plugin de monitor de salud de servidores...');
56
+ }
57
+
58
+ module.exports = { init, deinit };
@@ -0,0 +1,16 @@
1
+ {
2
+ "name": "Monitor de Salud de Servidores",
3
+ "version": "1.0.0",
4
+ "description": "Plugin para monitorear eventos de verificación de salud de servidores backend",
5
+ "author": "Sistema Kukuy",
6
+ "main": "index.js",
7
+ "kukuyVersion": "^1.6.0",
8
+ "hooks": [
9
+ "onHealthCheckStart",
10
+ "onHealthCheckComplete",
11
+ "onHealthCheckError",
12
+ "onHealthCheckTimeout",
13
+ "onHealthCheckException"
14
+ ],
15
+ "enabled": true
16
+ }
@@ -0,0 +1,172 @@
1
+ /**
2
+ * Plugin de Redirección para Kukuy
3
+ * Permite implementar reglas de redirección personalizadas
4
+ */
5
+
6
+ // Reglas de redirección
7
+ let redirectRules = [
8
+ // Ejemplo: redirigir /old-path a /new-path permanentemente
9
+ // { pattern: /^\/old-path$/, target: '/new-path', type: 'permanent' },
10
+ ];
11
+
12
+ /**
13
+ * Inicializa el plugin de redirección
14
+ * @param {Object} balancer - Instancia del balanceador
15
+ */
16
+ async function init(balancer) {
17
+ console.log('Inicializando plugin de redirección...');
18
+
19
+ const extension = balancer.getPostStartupExtension();
20
+
21
+ // Registrar filtro para procesar solicitudes
22
+ extension.registerFilter('request_processing', requestProcessingFilter, 2);
23
+
24
+ // Registrar hook para cuando se recibe una solicitud
25
+ extension.registerHook('onRequestReceived', onRequestReceivedHook, 2);
26
+
27
+ // Cargar reglas de redirección desde el entorno
28
+ loadRedirectRulesFromEnv();
29
+
30
+ console.log('Plugin de redirección inicializado correctamente');
31
+ }
32
+
33
+ /**
34
+ * Carga reglas de redirección desde variables de entorno
35
+ */
36
+ function loadRedirectRulesFromEnv() {
37
+ if (process.env.REDIRECT_RULES) {
38
+ try {
39
+ const rules = JSON.parse(process.env.REDIRECT_RULES);
40
+ redirectRules = [...redirectRules, ...rules];
41
+ console.log(`[REDIRECT-PLUGIN] Cargadas ${rules.length} reglas de redirección desde entorno`);
42
+ } catch (error) {
43
+ console.error('[REDIRECT-PLUGIN] Error al parsear reglas de redirección desde entorno:', error.message);
44
+ }
45
+ }
46
+ }
47
+
48
+ /**
49
+ * Filtro para procesar solicitudes
50
+ * @param {Object} data - Datos de la solicitud
51
+ * @returns {Object} - Resultado del procesamiento
52
+ */
53
+ async function requestProcessingFilter(data) {
54
+ const { req, res } = data;
55
+
56
+ // Buscar una regla de redirección que coincida
57
+ for (const rule of redirectRules) {
58
+ if (rule.pattern instanceof RegExp) {
59
+ // Si el patrón es una expresión regular
60
+ if (rule.pattern.test(req.url)) {
61
+ // Encontramos una coincidencia, realizar la redirección
62
+ const target = typeof rule.target === 'function'
63
+ ? rule.target(req.url)
64
+ : rule.target;
65
+
66
+ const statusCode = rule.type === 'permanent' ? 301 : 302;
67
+
68
+ res.writeHead(statusCode, {
69
+ 'Location': target,
70
+ 'Content-Type': 'text/html'
71
+ });
72
+
73
+ res.end(`<html><body>Redirigido a <a href="${target}">${target}</a></body></html>`);
74
+
75
+ console.log(`[REDIRECT-PLUGIN] Redirección ${statusCode} de ${req.url} a ${target}`);
76
+
77
+ return {
78
+ allowed: false, // Indicar que no debe continuar con el procesamiento normal
79
+ redirected: true,
80
+ redirectUrl: target,
81
+ statusCode
82
+ };
83
+ }
84
+ } else if (typeof rule.pattern === 'string') {
85
+ // Si el patrón es una cadena, verificar coincidencia exacta o parcial
86
+ if (req.url === rule.pattern || (rule.partialMatch && req.url.startsWith(rule.pattern))) {
87
+ // Encontramos una coincidencia, realizar la redirección
88
+ const target = typeof rule.target === 'function'
89
+ ? rule.target(req.url)
90
+ : rule.target;
91
+
92
+ const statusCode = rule.type === 'permanent' ? 301 : 302;
93
+
94
+ res.writeHead(statusCode, {
95
+ 'Location': target,
96
+ 'Content-Type': 'text/html'
97
+ });
98
+
99
+ res.end(`<html><body>Redirigido a <a href="${target}">${target}</a></body></html>`);
100
+
101
+ console.log(`[REDIRECT-PLUGIN] Redirección ${statusCode} de ${req.url} a ${target}`);
102
+
103
+ return {
104
+ allowed: false, // Indicar que no debe continuar con el procesamiento normal
105
+ redirected: true,
106
+ redirectUrl: target,
107
+ statusCode
108
+ };
109
+ }
110
+ }
111
+ }
112
+
113
+ // No se encontró ninguna regla de redirección, continuar normalmente
114
+ return { allowed: true, redirected: false };
115
+ }
116
+
117
+ /**
118
+ * Hook para cuando se recibe una solicitud
119
+ * @param {Object} params - Parámetros del hook
120
+ */
121
+ async function onRequestReceivedHook({ req, res }) {
122
+ console.log(`[REDIRECT-PLUGIN] Solicitud recibida: ${req.method} ${req.url}`);
123
+
124
+ // Podríamos hacer alguna lógica aquí si es necesario
125
+ }
126
+
127
+ /**
128
+ * Agrega una nueva regla de redirección
129
+ * @param {Object} rule - Regla de redirección
130
+ */
131
+ function addRedirectRule(rule) {
132
+ redirectRules.push(rule);
133
+ console.log(`[REDIRECT-PLUGIN] Añadida nueva regla de redirección: ${rule.pattern} -> ${rule.target}`);
134
+ }
135
+
136
+ /**
137
+ * Obtiene todas las reglas de redirección
138
+ * @returns {Array} - Array de reglas de redirección
139
+ */
140
+ function getRedirectRules() {
141
+ return redirectRules;
142
+ }
143
+
144
+ /**
145
+ * Limpia todas las reglas de redirección
146
+ */
147
+ function clearRedirectRules() {
148
+ redirectRules = [];
149
+ console.log('[REDIRECT-PLUGIN] Reglas de redirección limpiadas');
150
+ }
151
+
152
+ /**
153
+ * Desinicializa el plugin
154
+ * @param {Object} balancer - Instancia del balanceador
155
+ */
156
+ async function deinit(balancer) {
157
+ console.log('Desactivando plugin de redirección...');
158
+
159
+ // Limpiar recursos si es necesario
160
+ redirectRules = [];
161
+
162
+ console.log('Plugin de redirección desactivado correctamente');
163
+ }
164
+
165
+ // Exportar funciones
166
+ module.exports = {
167
+ init,
168
+ deinit,
169
+ addRedirectRule,
170
+ getRedirectRules,
171
+ clearRedirectRules
172
+ };
@@ -0,0 +1,15 @@
1
+ {
2
+ "name": "Plugin de Redirección",
3
+ "version": "1.0.0",
4
+ "description": "Plugin para implementar redirecciones basadas en reglas personalizadas",
5
+ "author": "Sistema Kukuy",
6
+ "main": "index.js",
7
+ "kukuyVersion": "^1.6.0",
8
+ "hooks": [
9
+ "onRequestReceived"
10
+ ],
11
+ "filters": [
12
+ "request_processing"
13
+ ],
14
+ "enabled": false
15
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "kukuy",
3
- "version": "1.5.0",
4
- "description": "Balanceador de carga Backend",
3
+ "version": "1.9.0",
4
+ "description": "Balanceador de carga con soporte para hooks, filtros y cache robusto",
5
5
  "main": "kukuy.js",
6
6
  "scripts": {
7
7
  "start": "node kukuy.js",
@@ -14,7 +14,11 @@
14
14
  "ip-hash",
15
15
  "proxy",
16
16
  "http",
17
- "https"
17
+ "https",
18
+ "hooks",
19
+ "filters",
20
+ "cache",
21
+ "plugins"
18
22
  ],
19
23
  "author": "Benjamín Sánchez Cárdenas",
20
24
  "license": "GPL-3.0-or-later",
package/servers_real.json CHANGED
@@ -14,6 +14,11 @@
14
14
  "url": "http://localhost:5445",
15
15
  "weight": 1,
16
16
  "tags": ["backend"]
17
+ },
18
+ {
19
+ "url": "http://localhost:6666",
20
+ "weight": 1,
21
+ "tags": ["backend"]
17
22
  }
18
23
  ]
19
24
  }