
La arquitectura de microservicios estructura una aplicación como una colección de servicios débilmente acoplados y que se pueden implementar de forma independiente. Cada servicio posee una capacidad comercial específica, tiene su propio almacén de datos y se comunica a través de una red. Si bien los microservicios introducen una complejidad operativa significativa, permiten a las organizaciones escalar equipos de desarrollo, implementar de forma independiente y construir sistemas más resistentes.
La arquitectura de microservicios estructura una aplicación como una colección de servicios débilmente acoplados y que se pueden implementar de forma independiente. Cada servicio posee una capacidad comercial específica, tiene su propio almacén de datos y se comunica a través de una red. Si bien los microservicios introducen una complejidad operativa significativa, permiten a las organizaciones escalar equipos de desarrollo, implementar de forma independiente y construir sistemas más resistentes.
Una aplicación monolítica tiene todas las funciones en una única base de código y unidad de implementación:
┌─────────────────────────────────────────────┐
│ Monolith Application │
├──────────────┬──────────────┬───────────────┤
│ User Module │ Order Module│ Payment │
│ (controllers, services, repos, DB tables) │
└──────────────┴──────────────┴───────────────┘
Ventajas del monolito:
Desventajas del monolito:
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ User Service │ │ Order Service │ │ Payment Service │
│ (own DB, API) │ │ (own DB, API) │ │ (own DB, API) │
└────────┬─────────┘ └────────┬─────────┘ └────────┬─────────┘
│ │ │
└──────────────────────┼──────────────────────┘
│
┌───────────▼───────────┐
│ API Gateway │
│ (auth, routing) │
└───────────────────────┘
Cada servicio posee exactamente una capacidad comercial. Si puede describir el propósito de un servicio sin utilizar "y", es probable que tenga un buen alcance.
Bien:
servicio de pago: gestiona el procesamiento de pagos y los reembolsos.servicio de notificaciones: envía correos electrónicos, SMS y notificaciones automáticas.inventory-service: gestiona los niveles de stock y las reservas.Malo:
backend-service: todo en un solo servicio (ningún microservicio).Cada servicio es dueño de su base de datos. Los servicios nunca comparten bases de datos: se comunican a través de API.
-- Service A has its own database
CREATE TABLE users (
id UUID PRIMARY KEY,
email VARCHAR(255) UNIQUE,
name VARCHAR(255)
);
-- Service B has its own database, stores only the user ID
CREATE TABLE orders (
id UUID PRIMARY KEY,
user_id UUID NOT NULL,
total DECIMAL(10,2),
status VARCHAR(50)
);
¿Por qué no compartir bases de datos?
Una falla en un servicio no debería afectar a otros.
Patrón de disyuntor:
// Using a circuit breaker to handle service failures gracefully
const breaker = new CircuitBreaker({
failureThreshold: 5,
resetTimeout: 30000, // 30 seconds
});
async function getPaymentStatus(orderId: string) {
try {
return await breaker.call(() => paymentService.getStatus(orderId));
} catch (error) {
// Fallback: return cached status or default
return { status: 'pending', note: 'Payment service unavailable' };
}
}
Patrón de mamparo: Asigne grupos de subprocesos separados para diferentes servicios para que un servicio lento no agote todos los recursos:
// Separate thread pools per service
const paymentPool = new ThreadPool({ maxThreads: 10 });
const inventoryPool = new ThreadPool({ maxThreads: 20 });
const notificationPool = new ThreadPool({ maxThreads: 5 });
Cada servicio se puede implementar de forma independiente. Este es el principal beneficio de los microservicios.
Automatización de la implementación:
# GitHub Actions for a single microservice
name: Deploy Payment Service
on:
push:
paths:
- 'services/payment/**'
- '.github/workflows/payment.yml'
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: docker build -t payment-service .
- run: docker push registry.example.com/payment-service:${{ github.sha }}
- run: kubectl set image deployment/payment-service payment-service=registry.example.com/payment-service:${{ github.sha }}
Pros: Fácil de implementar y razonar. La semántica de solicitud-respuesta es familiar.
Contras: Crea un acoplamiento en tiempo de ejecución: si el servicio descendente no funciona, la persona que llama se ve afectada.
// REST call using fetch
const order = await fetch(`http://order-service:8080/api/orders/${orderId}`);
// gRPC definition
service OrderService {
rpc GetOrder (GetOrderRequest) returns (Order);
}
message GetOrderRequest {
string order_id = 1;
}
Ventajas: Acoplamiento flexible, mejor resiliencia y admite arquitecturas basadas en eventos.
Contras: La coherencia final, más difícil de depurar, requiere infraestructura de mensajes.
// Kafka producer
await producer.send({
topic: 'order.created',
messages: [{ value: JSON.stringify({ orderId, userId, total }) }]
});
// Kafka consumer in notification service
await consumer.run({
eachMessage: async ({ message }) => {
const { orderId, userId } = JSON.parse(message.value.toString());
await emailService.sendOrderConfirmation(userId, orderId);
}
});
| Criterios | Sincrónico | Asincrónico |
|---|---|---|
| ¿La persona que llama necesita una respuesta inmediata? | Sí | No |
| ¿Se puede aplazar la operación? | No | Sí |
| ¿El servicio downstream está siempre disponible? | Sí | No requerido |
| ¿Necesitas una fuerte consistencia? | Sí | Eventual está bien |
// Strangler Fig pattern
const gateway = express();
// Route to new service if available, fall back to monolith
gateway.use('/api/users', async (req, res, next) => {
try {
const response = await fetch('http://user-service/api/users' + req.path);
return res.json(await response.json());
} catch {
next(); // Fall through to monolith handler
}
});
| Tamaño del servicio | Tamaño del equipo | Frecuencia de implementación | Ejemplo |
|---|---|---|---|
| ⚡ Pequeño | 1-3 desarrolladores | Varias veces/día | Verificación de usuario |
| 📐 Medio | 3-6 desarrolladores | Diario/semanal | Procesamiento de pedidos |
| 🏗️ Grande | 6-10 desarrolladores | Semanalmente | Plataforma de pago |
Regla general: Un servicio debe ser lo suficientemente pequeño como para que un solo equipo pueda poseerlo por completo, y lo suficientemente grande como para proporcionar un valor comercial significativo.
Los microservicios generan enormes cantidades de telemetría. Tres pilares:
1. Registro:
// Structured logging (JSON)
{
"timestamp": "2026-05-24T10:30:00.123Z",
"level": "error",
"service": "payment-service",
"trace_id": "abc123",
"message": "Payment processing failed",
"error": "stripe: insufficient funds",
"metadata": { "order_id": "ord_456", "amount": 2999 }
}
2. Métricas (formato Prometheus):
# HELP http_requests_total Total HTTP requests
# TYPE http_requests_total counter
http_requests_total{method="POST",path="/api/payments",status="500"} 42
3. Seguimiento distribuido (OpenTelemetry):
# OpenTelemetry auto-instrumentation
OTEL_EXPORTER_OTLP_ENDPOINT: "http://otel-collector:4318"
OTEL_SERVICE_NAME: "payment-service"
OTEL_TRACES_SAMPLER: "parentbased_traceidratio"
OTEL_TRACES_SAMPLER_ARG: "0.1"
En entornos dinámicos (Kubernetes), las direcciones IP cambian. Los servicios se encuentran entre sí a través de DNS:
pago-servicio.namespace.svc.cluster.local.Un único punto de entrada para todas las solicitudes de los clientes:
| Función | Ejemplo |
|---|---|
| Enrutamiento | /api/users → servicio-usuario, /api/orders → servicio-pedido |
| Autenticación | Validar tokens JWT antes de enrutar |
| Limitación de velocidad | 1000 solicitudes/min por cliente |
| Solicitar transformación | Convertir JSON a Protobuf |
| Almacenamiento en caché de respuestas | Caché de respuestas GET |
| ruptura de circuito | Dejar de dirigirse a servicios en mal estado |
Externalizar toda la configuración:
# ConfigMap in Kubernetes
apiVersion: v1
kind: ConfigMap
metadata:
name: payment-service-config
data:
DATABASE_URL: "postgresql://..."
STRIPE_API_KEY: "${STRIPE_API_KEY}" # from Secret
MAX_RETRIES: "3"
FEATURE_FLAG_NEW_CHECKOUT: "true"
apiVersion: apps/v1
kind: Deployment
metadata:
name: payment-service
spec:
replicas: 3
selector:
matchLabels:
app: payment-service
template:
metadata:
labels:
app: payment-service
spec:
containers:
- name: payment-service
image: registry.example.com/payment-service:latest
ports:
- containerPort: 8080
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
Ley de Conway: Las organizaciones diseñan sistemas que reflejan su estructura de comunicación. Si su equipo no está organizado en torno a los límites de los servicios, los microservicios crearán fricciones.
| Categoría | Opciones | Notas |
|---|---|---|
| Estructura | Spring Boot, NestJS, FastAPI, kit Go | Elija según la experiencia del equipo |
| API | DESCANSO, gRPC, GraphQL | gRPC para interno, REST para externo |
| Mensajería | Kafka, RabbitMQ, NATS | Kafka para un alto rendimiento |
| Base de datos | PostgreSQL, DynamoDB, MongoDB | Haga coincidir la base de datos con las necesidades del servicio |
| Recipiente | Estibador | Universal |
| Orquestación | Kubernetes | EKS, AKS, GKE o autogestionado |
| Puerta de enlace API | Kong, enviado, puerta de enlace API de AWS | Enviado para la integración de la malla de servicios |
| Observabilidad | OpenTelemetry, Prometheus, Jaeger | OpenTelemetry es el estándar |
| CI/CD | Acciones de GitHub, GitLab CI, ArgoCD | ArgoCD para GitOps |
| Malla de servicio | Istio, Linkerd, Cilio | Linkerd para simplificar |
| Gestión Secreta | HashiCorp Vault, administrador de secretos de AWS | Bóveda para múltiples nubes |
Los microservicios son un poderoso patrón arquitectónico que permite una implementación independiente, autonomía del equipo y sistemas escalables. Sin embargo, conllevan una complejidad operativa significativa. Las adopciones de microservicios más exitosas:
Los microservicios no son la arquitectura predeterminada: son una solución a problemas organizativos y de escala específicos. Elíjalos deliberadamente, no por defecto.
Todavía no hay comentarios aprobados. Las respuestas nuevas pueden esperar moderación.