Introducción: ¿Por qué microservicios en JavaScript?
\nEl desarrollo web moderno se aleja cada vez más de las aplicaciones monolíticas en favor de la arquitectura de microservicios. JavaScript, o más precisamente su entorno de servidor Node.js, es ideal para construir microservicios gracias a su asincronía, modelo orientado a eventos y enorme comunidad de ecosistema. En este artículo, analizaremos cómo diseñar, desarrollar e implementar microservicios en JavaScript, desde la teoría hasta ejemplos prácticos de código.
\n\n1. Fundamentos de la arquitectura de microservicios
\nLa arquitectura de microservicios es un enfoque en el que una aplicación se divide en servicios pequeños e independientes. Cada servicio se encarga de su propia lógica de negocio, tiene su propio almacenamiento de datos y puede implementarse, escalarse y actualizarse por separado.
\nVentajas de los microservicios en Node.js
\n- \n
- Escalabilidad: Node.js maneja fácilmente miles de conexiones simultáneas gracias a su E/S sin bloqueo. \n
- Prototipado rápido: Los paquetes npm y frameworks (Express, Fastify, NestJS) permiten crear rápidamente APIs REST/GraphQL. \n
- Aislamiento de errores: Una falla en un servicio no paraliza toda la aplicación. \n
- Flexibilidad tecnológica: Diferentes servicios pueden usar diferentes versiones de Node.js o incluso diferentes lenguajes. \n
Componentes clave
\n- \n
- API Gateway — punto de entrada único que enruta las solicitudes a los servicios correspondientes. \n
- Broker de mensajes (RabbitMQ, Redis, Kafka) — para el intercambio asíncrono de datos. \n
- Registro de servicios (Consul, etcd) — para el descubrimiento de servicios. \n
- Contenedorización (Docker, Kubernetes) — para estandarizar el entorno. \n
2. Práctica: Creando dos microservicios
\nAnalicemos un ejemplo de sistema de pedidos. Tendremos dos microservicios: user-service (gestión de usuarios) y order-service (gestión de pedidos). Se comunicarán a través de una API REST y de forma asíncrona mediante RabbitMQ.
2.1. Servicio básico con Express
\nEmpecemos con user-service. Instale las dependencias:
npm init -y\nnpm install express body-parser\nCree el archivo index.js:
const express = require('express');\nconst bodyParser = require('body-parser');\nconst app = express();\nconst PORT = process.env.PORT || 3001;\n\napp.use(bodyParser.json());\n\nconst users = [];\n\napp.post('/users', (req, res) => {\n const { name, email } = req.body;\n const user = { id: users.length + 1, name, email };\n users.push(user);\n res.status(201).json(user);\n});\n\napp.get('/users/:id', (req, res) => {\n const user = users.find(u => u.id === parseInt(req.params.id));\n if (!user) return res.status(404).json({ error: 'User not found' });\n res.json(user);\n});\n\napp.listen(PORT, () => {\n console.log(`User service running on port ${PORT}`);\n});\nDe manera similar, cree order-service en el puerto 3002. Contendrá un array de pedidos y dos endpoints: POST /orders y GET /orders/:id.
2.2. API Gateway
\nCreemos una puerta de enlace simple en el puerto 3000 que redirija las solicitudes según la ruta:
\nconst express = require('express');\nconst httpProxy = require('http-proxy-middleware');\nconst app = express();\n\napp.use('/users', httpProxy.createProxyMiddleware({ target: 'http://localhost:3001', changeOrigin: true }));\napp.use('/orders', httpProxy.createProxyMiddleware({ target: 'http://localhost:3002', changeOrigin: true }));\n\napp.listen(3000, () => console.log('API Gateway on port 3000'));\nAhora todas las solicitudes a /users van al user-service, y las de /orders al order-service.
2.3. Interacción asíncrona con RabbitMQ
\nSupongamos que al crear un pe