Reunindo Microserviços para Maior Coesão

Depois de adotar uma arquitetura de microserviços, é comum perceber que alguns aspectos precisam ser unificados ou “centralizados” de alguma forma, para garantir coerência, reuso e facilidade de manutenção. Neste primeiro artigo de uma nova série, analisaremos por que e como podemos retomar certa “coesão” no ecossistema de microserviços sem abrir mão dos benefícios da divisão. Falaremos de um panorama geral de quatro possíveis estratégias:

  1. Replicação de Código
  2. Biblioteca Compartilhada
  3. Serviço Compartilhado
  4. Sidecars e Malhas de Serviços

Nos artigos subsequentes, cada estratégia será aprofundada em um post específico, detalhando vantagens, desvantagens e melhores práticas de implementação.


1. O Contexto: Microserviços e Fragmentação

1.1 Por que Microserviços?

  • Escalabilidade e independência de deploy: cada serviço pode evoluir e ser escalado separadamente.
  • Equipes autônomas: times podem trabalhar em serviços distintos de forma independente.
  • Resiliência: falha em um serviço não derruba todo o sistema.

1.2 O Problema da “Fragmentação Demais”

Com o tempo, pode-se perceber:

  • Funcionalidades ou lógicas repetidas em vários serviços.
  • Padrões de segurança, validação ou logging duplicados.
  • APIs que precisam se comunicar intensamente ou que têm muita sobreposição, resultando em complexidade adicional.

É quando se vê a necessidade de “reunir” certos elementos, sem retornar a um monólito. Surge então a pergunta: “Como ganhar coesão novamente?”


2. Estratégias para Reunir o Essencial sem Voltarmos ao Monólito

2.1 Replicação de Código

Ideia: Copiar e colar código (classes, módulos) em cada microserviço, de forma deliberada. Esse código replicado pode ser um conjunto de utilitários ou lógica de negócio comum.

  • Prós: Simples (não depende de repositório único ou bibliotecas); cada serviço retém total autonomia.
  • Contras: Se precisar corrigir um bug ou evoluir a lógica compartilhada, é preciso atualizar cada serviço manualmente.

2.2 Biblioteca Compartilhada

Ideia: Extrair lógicas comuns em uma biblioteca (jar, npm package, gem, etc.) que cada serviço importa como dependência.

  • Prós: Centraliza a manutenção do código comum; qualquer atualização na biblioteca pode ser versionada e distribuída.
  • Contras: Exige pipeline de publicação e versionamento adequados, e ainda assim, cada serviço precisa atualizar a dependência para receber correções.

2.3 Serviço Compartilhado

Ideia: Criar um microserviço “base” que concentra determinadas funcionalidades e é consumido pelos demais via API.

  • Prós: Se algo precisa ser corrigido/evoluído, faz-se centralmente; evita duplicação de código.
  • Contras: Pode se tornar um “macro-serviço” ou “God service”, aumentando acoplamento e criando dependência forte dos demais.

2.4 Sidecars e Malhas de Serviços (Service Mesh)

Ideia: Usar sidecars (containers “auxiliares” acoplados a cada microserviço) e/ou uma service mesh (ex.: Istio, Linkerd) que forneça funcionalidades de forma unificada (observabilidade, segurança, roteamento).

  • Prós: Garante padronização de logging, tracing, segurança, sem duplicar lógica na aplicação.
  • Contras: A complexidade de orquestrar sidecars e configurar a mesh pode ser grande; necessidade de estudar e operar infraestrutura mais avançada.

3. Quando Escolher Cada Estratégia?

3.1 Replicação de Código

  • Indicada quando a lógica comum é relativamente pequena e estável, e a equipe não quer ou não pode manter dependências oficiais.
  • Cuidado para não gerar problemas de divergência ao longo do tempo.

3.2 Biblioteca Compartilhada

  • Boa quando queremos reusar código de forma coesa e controlada, atualizando via versionamento sem copiar e colar.
  • Exige pipeline de CI/CD e versionamento claro, além de um repositório (Nexus, Artifactory, npm registry privado, etc.).

3.3 Serviço Compartilhado

  • Útil quando existe uma API ou funcionalidade significativa que todos precisam e que pode ser oferecida por um microserviço dedicado (ex.: serviço de login, serviço de notificações).
  • Risco de se tornar um ponto central (risco de gargalo ou falhas em cascata) ou um “monólito interno”.

3.4 Sidecars e Malhas de Serviços

  • Excelente para padronizar aspectos transversais (log, tracing, segurança mTLS, roteamento inteligente), sem duplicar na aplicação.
  • Complexidade maior em setup e operação (Kubernetes, service mesh, observabilidade extra).

4. Considerações Finais

Essas estratégias não são excludentes. Um projeto pode:

  • Usar bibliotecas compartilhadas para a maior parte da lógica de utilitários.
  • Ter um serviço comum para funcionalidades mais robustas (ex.: relatório central).
  • Adotar sidecar ou service mesh para padronizar autenticação, logs e métricas de rede.
  • Replicar código em alguns casos menores, pela simplicidade de “copiar e colar”.

O importante é balancear a autonomia e os princípios dos microserviços (isolar responsabilidades, permitir evolução independente) com a necessidade de coesão e reuso. Ao longo desta série de artigos, discutiremos em maior detalhe cada estratégia:

  1. Replicação de Código
  2. Biblioteca Compartilhada
  3. Serviço Compartilhado
  4. Sidecars e Malhas de Serviços

para que você possa decidir como “reagrupar” certas partes da lógica ou infraestrutura sem romper a essência dos microserviços.


Próximos Passos

No próximo artigo, exploraremos a Replicação de Código em microserviços: quando é aceitável simplesmente duplicar trechos de lógica, quais os riscos e como gerenciar versões copiadas de forma minimamente controlada. Fique atento!

Notas Bibliográficas

  1. Arquitetura de Software: As Partes Difíceis. Editora Alta Books.