Software · Arquitetura de Software

Arquitetura de Microsserviços: Decomposição por Domínio, Autonomia e Resiliência

Como estruturar microsserviços autônomos por Bounded Contexts, gerenciar persistência isolada e balancear a complexidade distribuída com API Gateways.

Diagrama conceitual de arquitetura de microsserviços com decomposição por contexto e tráfego via gateway
Neste artigo

A Arquitetura de Microsserviços estrutura um sistema como um conjunto de serviços autônomos, de granularidade fina e fracamente acoplados, em que cada unidade responde por uma única capacidade de negócio delimitada por um Bounded Context. Diferente do desenvolvimento em monólitos tradicionais, onde toda a base de código é compilada e implantada de forma monolítica, os microsserviços possuem ciclos de vida de compilação, teste e implantação completamente independentes.

Essa independência viabiliza times autônomos trabalhando em paralelo e permite escalar recursos de computação cirurgicamente: se o módulo de pagamentos enfrenta picos de demanda durante uma promoção, apenas as instâncias de pagamento são escaladas horizontalmente, sem necessidade de multiplicar os recursos dedicados ao catálogo ou à emissão de relatórios.

Pilares Arquiteturais dos Microsserviços

Para colher os benefícios reais desse modelo sem transformá-lo em um emaranhado caótico de dependências de rede, quatro princípios devem ser rigorosamente observados:

graph TD
    Clients["<b>Clientes Web / Mobile</b>"] --> GW["<b>API Gateway</b><br/>(Auth, Rate Limit, Agregação)"]

    GW -->|gRPC / HTTP| S_Ped["<b>Serviço Pedidos</b>"]
    GW -->|gRPC / HTTP| S_Est["<b>Serviço Estoque</b>"]
    GW -->|gRPC / HTTP| S_Usu["<b>Serviço Usuário</b>"]

    S_Ped --> DB1[("DB Pedidos")]
    S_Est --> DB2[("DB Estoque")]
    S_Usu --> DB3[("DB Usuários")]

    S_Ped -.->|Publica Eventos| Kafka[["Barramento de Eventos (Kafka)"]]
    S_Est -.->|Publica Eventos| Kafka
    S_Usu -.->|Publica Eventos| Kafka

    classDef client fill:#0f172a,stroke:#64748b,stroke-width:1px,color:#f8fafc;
    classDef gateway fill:#132338,stroke:#38bdf8,stroke-width:2px,color:#f8fafc;
    classDef svc fill:#1e293b,stroke:#4ade80,stroke-width:1px,color:#f8fafc;
    classDef db fill:#1e1b4b,stroke:#a855f7,stroke-width:1px,color:#f8fafc;
    classDef bus fill:#0f2724,stroke:#34d399,stroke-width:2px,color:#f8fafc;

    class Clients client;
    class GW gateway;
    class S_Ped,S_Est,S_Usu svc;
    class DB1,DB2,DB3 db;
    class Kafka bus;

1. Banco de Dados Isolado por Serviço (Database per Service)

Cada microsserviço deve gerenciar sua própria base de persistência. O compartilhamento de um banco de dados relacional centralizado entre múltiplos serviços representa o anti-padrão mais comum do mercado, pois recria o acoplamento monolítico na camada de dados: qualquer migração de coluna ou bloqueio de tabela (table lock) derruba serviços adjacentes. Se o Serviço de Pedidos necessita de dados de clientes, ele consulta a API pública do Serviço de Usuários ou assina eventos de sincronização, nunca executando junções SQL diretas nas tabelas alheias.

2. Protocolos de Comunicação Inteligentes e Simples

A integração opera sob a filosofia de dumb pipes, smart endpoints (canais simples com lógica nas pontas). Para chamadas síncronas de baixa latência entre serviços internos, utilizam-se contratos fortemente tipados em gRPC ou interfaces RESTful; para desacoplamento temporal e propagação de mudanças de estado, adotam-se corretores assíncronos como Kafka ou RabbitMQ.

3. Autonomia de Implantação e Contêineres

Os serviços são empacotados em contêineres imutáveis (Docker) contendo suas próprias dependências de runtime e orquestrados em plataformas elásticas como Kubernetes. Uma falha ou atualização no serviço de notificações não interrompe a esteira do serviço de checkout.

4. O Papel do API Gateway

Expor dezenas de microsserviços diretamente aos navegadores e celulares expõe a arquitetura interna e cria complexidade na gestão de segurança. O padrão API Gateway estabelece um ponto único de entrada que centraliza:

  • Roteamento Dinâmico: Encaminha chamadas com base em prefixos de rota para os nós internos corretos.
  • Autenticação e Autorização: Valida tokens JWT antes que a requisição atinja a rede privada dos serviços.
  • Agregação de Respostas: Consolida dados de diferentes serviços em uma única resposta compacta para dispositivos móveis, reduzindo o número de viagens de ida e volta pela internet (round-trips).
  • Controle de Vazão (Rate Limiting): Protege os serviços internos contra sobrecargas repentinas ou ataques automatizados.

Comparativo: Microsserviços versus SOA Tradicional

É frequente a comparação entre microsserviços e a Arquitetura Orientada a Serviços (SOA) corporativa dos anos 2000, contudo suas premissas de engenharia divergem frontalmente:

Dimensão Microsserviços SOA Corporativa Tradicional
Granularidade Fina: orientada a contextos delimitados específicos. Grossa: serviços amplos cobrindo divisões corporativas inteiras.
Barramento Fios simples (dumb pipes) como filas de mensagens enxutas. Barramento corporativo pesado (ESB) contendo regras de negócio e transformações XML.
Persistência Descentralizada: banco dedicado por serviço (poliglotismo). Centralizada: banco de dados corporativo compartilhado.
Governança Descentralizada: equipes escolhem suas linguagens e ferramentas. Centralizada: comitês rígidos e padrões padronizados para toda a empresa.

Os Custos e Desafios Reais da Distribuição

Embora ofereçam autonomia e escala técnica, os microsserviços cobram um preço operacional elevado que não deve ser subestimado:

  1. Falácias da Computação Distribuída: A rede não é confiável nem instantânea. Toda chamada entre serviços pode sofrer lentidão ou perda de pacotes, exigindo padrões de resiliência como Circuit Breaker, Retries exponenciais com jitter e Timeouts rigorosos.
  2. Consistência e Transações: Transações ACID clássicas não existem entre serviços independentes. A atomicidade de processos que envolvem múltiplos contextos exige o padrão Saga (orquestrado ou coreografado) com transações compensatórias em caso de falha no meio do caminho.
  3. Observabilidade Contínua: Diagnosticar um erro exige rastreamento distribuído ponta a ponta (OpenTelemetry), agregação centralizada de logs e métricas de latência p99 por rota.

Por esses motivos, a recomendação prática predominante na indústria para equipes em fase inicial é começar com um Monólito Modular bem delimitado: as fronteiras de domínio são construídas no código desde o primeiro dia, preservando a facilidade operacional até que o volume de transações ou a escala organizacional realmente exijam a divisão física em microsserviços.

Explorar este tema no Grafo de Conhecimento