Microsserviços
Como decompor um sistema em serviços pequenos, autônomos e implantáveis de forma independente, alinhados com domínios de negócio.
Que problema resolve
À medida que uma aplicação monolítica cresce, surgem problemas que travam a equipe:
- Implantações arriscadas: Uma mudança pequena exige reimplantar toda a aplicação
- Escalabilidade ineficiente: Para escalar uma funcionalidade, você precisa escalar o monolito inteiro
- Equipes bloqueadas: Múltiplas equipes trabalham na mesma base de código e se bloqueiam mutuamente
- Tecnologia homogênea: Todo o sistema precisa usar a mesma linguagem, framework e banco de dados
- Tempo de build crescente: Compilar e testar todo o monolito leva cada vez mais tempo
Monolito:
┌─────────────────────────────────┐
│ Aplicação │
│ ┌─────┐ ┌─────┐ ┌──────────┐ │
│ │Users│ │Prods│ │ Orders │ │
│ └─────┘ └─────┘ └──────────┘ │
│ ┌─────────────────────────────┐│
│ │ Base de datos única ││
│ └─────────────────────────────┘│
└─────────────────────────────────┘
Un deploy = todo el sistema
Un fallo = todo el sistema
Como funciona
A arquitetura de microsserviços decompõe o sistema em serviços pequenos e independentes, cada um responsável por uma capacidade de negócio específica. Cada serviço:
- Tem seu próprio banco de dados (Database per Service)
- É implantado de forma independente
- Comunica-se com outros serviços por meio de APIs ou eventos
- Pertence a uma equipe específica
Microservicios:
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Users │ │ Products │ │ Orders │
│ Service │ │ Service │ │ Service │
│ ┌────┐ │ │ ┌────┐ │ │ ┌────┐ │
│ │ DB │ │ │ │ DB │ │ │ │ DB │ │
│ └────┘ │ │ └────┘ │ │ └────┘ │
└──────────┘ └──────────┘ └──────────┘
│ │ │
└──────── Event Bus ─────────┘
Princípios de decomposição
A chave está em como dividir o sistema. Os critérios mais eficazes são:
| Critério | Descrição | Exemplo |
|---|---|---|
| Por domínio de negócio | Cada serviço representa um bounded context do DDD | User Service, Order Service, Payment Service |
| Por capacidade de negócio | Cada serviço implementa uma capacidade organizacional | Faturamento, Estoque, Notificações |
| Por subdomain | Alinhado com subdomínios do negócio | Core (pedidos), Supporting (relatórios), Generic (auth) |
Comunicação entre serviços
Os microsserviços se comunicam de duas formas principais:
Síncrona (request-response):
Order Service ──HTTP/gRPC──► Product Service
"¿Hay stock del producto X?"
← "Sí, 50 unidades"
Assíncrona (eventos):
Order Service ──evento──► Event Bus ──► Inventory Service
"OrderCreated" "Reservar stock"
──► Notification Service
"Enviar email"
Database per Service
Cada microsserviço é dono dos seus dados. Nenhum outro serviço acessa diretamente o seu banco de dados:
✅ Correcto:
Order Service ──API──► User Service
"Dame el nombre del usuario 123"
❌ Incorrecto:
Order Service ──SQL──► User DB
"SELECT name FROM users WHERE id=123"
Isso garante o encapsulamento e permite que cada serviço escolha a tecnologia de armazenamento mais adequada (SQL, NoSQL, cache, etc.).
Vantagens
- Implantação independente: Cada serviço é implantado sem afetar os demais
- Escalabilidade granular: Escale apenas os serviços que precisam
- Autonomia das equipes: Cada equipe é dona do seu serviço de ponta a ponta
- Diversidade tecnológica: Cada serviço pode usar a linguagem e o framework mais adequados
- Resiliência: Uma falha em um serviço não necessariamente derruba todo o sistema
- Time to market: Equipes pequenas conseguem entregar mais rápido
Trade-offs / Desvantagens
- Complexidade distribuída: Debugging, testing e tracing são significativamente mais difíceis
- Consistência eventual: As transações distribuídas são complexas (exigem Sagas, Outbox)
- Latência de rede: A comunicação entre serviços adiciona latência
- Overhead operacional: Mais serviços = mais implantações, mais monitoramento, mais infraestrutura
- Duplicação de dados: Cada serviço pode precisar de cópias de dados de outros serviços
- Complexidade organizacional: Exige equipes maduras com cultura DevOps
Quando usar
- Sistemas grandes com múltiplas equipes de desenvolvimento
- Quando diferentes partes do sistema têm requisitos de escalabilidade muito distintos
- Quando você precisa implantar funcionalidades de forma independente e frequente
- Organizações com equipes autônomas alinhadas com domínios de negócio
- Sistemas em que a resiliência e a disponibilidade são críticas
Quando evitar
- Equipes pequenas (menos de 8-10 desenvolvedores) onde o overhead não se justifica
- Sistemas com domínio simples que não requer decomposição
- Quando você não tem infraestrutura madura de CI/CD, monitoramento e orquestração
- Protótipos ou MVPs em que a velocidade de desenvolvimento é prioridade
- Quando você não consegue definir bounded contexts claros (sinal de que o domínio não está bem compreendido)
Tecnologias e implementações comuns
| Categoria | Opções |
|---|---|
| Comunicação síncrona | REST, gRPC, GraphQL |
| Comunicação assíncrona | Kafka, RabbitMQ, Amazon SQS, NATS |
| Orquestração | Kubernetes, Docker Swarm, Amazon ECS |
| Service Discovery | Consul, Eureka, DNS-based (Kubernetes) |
| Observabilidade | Jaeger, Zipkin, OpenTelemetry, Prometheus |
| API Gateway | Kong, Traefik, AWS API Gateway |
Relação com outros padrões
- DDD (Domain-Driven Design): Fornece os critérios para definir os limites de cada serviço
- API Gateway: Ponto de entrada único para os clientes externos
- Saga Pattern: Gerencia transações que cruzam múltiplos serviços
- Event-Driven Architecture: Padrão de comunicação assíncrona entre serviços
- Circuit Breaker: Protege os serviços de falhas em cascata
Próximos passos
Os microsserviços são um estilo arquitetural poderoso, porém exigente. Para entender como lidar com a comunicação assíncrona entre eles, explore Event-Driven Architecture. Para proteger a comunicação com sistemas externos, revise o Anti-Corruption Layer.