Skip to main content

Microservico | Arquitetura

  • Microservico | Arquitetura

Idempotência

  • Essa terminologia tem raízes na matemática e diz respeito ao conceito de que operações idênticas executadas repetidamente não devem alterar o resultado.
  • No REST, um método é considerado idempotente se o resultado de uma requisição realizada com sucesso é independente do número de vezes que é executada.
    • O método GET, PUT e DELETE são considerados idempotente. O POST não
      • Exemplo: supondo que tenhamos um retry pattern para alguma requisição POST, deve ser colocado um id da requisição para a aplicação que recebe saber se foi já mandado alguma request com o mesmo id
      • Qualquer operação que tenha retry pattern e não seja idempotente, temos que colocar um id da requisição. Uma solução é salvar esses ids em um dicionário dentro do Redis por um determinado tempo, de preferencia do tempo configurado no retry

ACID

imagem

O padrão Sidecar e o padrão API Gateway são dois padrões arquiteturais utilizados para resolver problemas comuns em arquiteturas de microsserviços, mas eles atuam em níveis diferentes e têm finalidades distintas. Vamos explorá-los em detalhes:

Padrão Sidecar - Código de Infra

Definição: O padrão Sidecar é um padrão de design onde um serviço auxiliar é implantado ao lado de um serviço principal em um contêiner separado, mas estreitamente acoplado. Esse serviço auxiliar fornece funcionalidades adicionais que não fazem parte da lógica principal do serviço, como logging, monitoramento, configuração, segurança, entre outros.

Características:

  • Desacoplamento: O sidecar desacopla funcionalidades auxiliares do serviço principal, promovendo uma maior modularidade.
  • Reutilização: O mesmo sidecar pode ser reutilizado por vários serviços que necessitam de funcionalidades semelhantes.
  • Isolamento: Facilita a atualização e manutenção das funcionalidades auxiliares sem impactar o serviço principal.

Exemplo: Um exemplo comum de sidecar é o uso do Envoy ou Istio como proxies para adicionar recursos de observabilidade, roteamento, e segurança a um serviço principal.

Padrão API Gateway

Definição: O padrão API Gateway é um ponto de entrada único para todas as chamadas de APIs de clientes para serviços backend. Ele atua como um intermediário que pode realizar tarefas como roteamento de requisições, agregação de respostas, autenticação, autorização, transformação de dados, entre outros.

Características:

  • Unificação: Centraliza a gestão de APIs, oferecendo um único ponto de entrada.
  • Segurança: Pode gerenciar autenticação e autorização, protegendo os serviços backend.
  • Escalabilidade: Ajuda na distribuição da carga e gerenciamento do tráfego.
  • Orquestração: Permite a combinação de múltiplos serviços em uma única resposta de API.

Exemplo: Ferramentas populares de API Gateway incluem Kong, Apigee, NGINX, e AWS API Gateway.

Relação entre Sidecar e API Gateway

Embora o padrão Sidecar e o padrão API Gateway sejam utilizados em contextos de microsserviços, eles têm finalidades e escopos diferentes:

  1. Nível de Operação:

    • Sidecar: Atua ao nível do serviço individual, fornecendo funcionalidades auxiliares específicas para cada serviço.
    • API Gateway: Atua ao nível da arquitetura, servindo como um ponto de entrada centralizado para todas as requisições de API.
  2. Funcionalidade:

    • Sidecar: Enfatiza a modularidade e reutilização de funcionalidades auxiliares, como logging e segurança.
    • API Gateway: Concentra-se em gestão e orquestração de chamadas de APIs, segurança centralizada e roteamento.
  3. Complementaridade:

    • Sidecar: Pode ser usado em conjunto com um API Gateway para fornecer funcionalidades adicionais a serviços individuais que o API Gateway não cobre diretamente.
    • API Gateway: Pode trabalhar em conjunto com sidecars para criar uma arquitetura robusta e segura, onde o gateway gerencia a entrada de requisições e os sidecars adicionam camadas de funcionalidade e segurança aos serviços internos.

Conclusão

Em resumo, o padrão Sidecar e o padrão API Gateway são componentes essenciais em uma arquitetura de microsserviços bem projetada. O Sidecar adiciona funcionalidades auxiliares diretamente aos serviços, enquanto o API Gateway gerencia o fluxo de requisições e fornece um ponto central de controle. Ambos podem ser usados juntos para construir sistemas escaláveis, modulares e seguros.

Anotações

  • Adicionar Polly para refazer tentativas em microsserviços é errado, deve ser usado um sidecar pattern. Em aplicações pequenas faz sentido usar Polly (sidecar fica responsável pelo time de plataforma)

Patterns

Failover

A lógica por trás do failover é bastante direta: quando um sistema primário falha ou fica inacessível por algum motivo (como uma falha de hardware, um erro de software ou um desastre natural), o failover automaticamente desloca as operações para um sistema secundário ou backup. Este sistema de backup, também conhecido como sistema standby, pode ser um espelho do sistema principal ou um sistema menos robusto que mantém as funções críticas até que o sistema principal seja restaurado.

Artigo Microservicos x Componentes - GAGO.io

O que é um microserviço?

Em linhas gerais, um microserviço é uma unidade de software autônoma e independente, responsável por um contexto de negócio bem definido. Ele deve ser:

  1. Separado por domínio (ou bounded context): cada microserviço cuida de um conjunto específico de regras de negócio.
  2. Implícita ou explicitamente desacoplado de outros microserviços: ele evolui e escala de forma independente.
  3. Responsável por gerenciar seus próprios dados (idealmente).

Quando dizemos “microserviço de pagamentos” ou “microserviço de catálogo” (no caso de um e-commerce), estamos nos referindo a toda a responsabilidade daquele domínio (pagamentos ou catálogo de produtos) e não apenas a um único processo/servidor que expõe uma API.

Componentes dentro de um mesmo microserviço

É comum — e muitas vezes necessário — que um microserviço possua diferentes componentes internos para atender a demandas específicas:

  • API (REST, gRPC, GraphQL etc.): Interface principal de comunicação para receber requisições síncronas.
  • Worker/Consumidor de Fila (job workersmessage consumers etc.): Responsável por processar tarefas em segundo plano, muitas vezes disparadas de forma assíncrona via mensageria (RabbitMQ, Kafka, etc.).
  • Scripts de migração (ou processos de migrate): Para manter o banco de dados ou outros recursos atualizados.
  • Tarefas Agendadas (cron jobs) ou processos de scheduler: Para executar rotinas periódicas.

Esses componentes podem ser divididos em diferentes deployments (containers, por exemplo) mas, conceitualmente, continuam pertencendo ao mesmo contexto. Logo, não são “outros microserviços”, e sim múltiplos componentes de um único microserviço.

Por que quebrar em componentes?

  • Melhor organização de código: separar responsabilidades no que tange a processamento em segundo plano, interface web etc.
  • Escalabilidade independente: a API pode precisar de mais réplicas para lidar com altas requisições HTTP, enquanto o worker pode escalar separadamente com base em volume de mensagens na fila.
  • Isolamento de falhas (até certo ponto): se o worker tiver um problema, não necessariamente afeta a interface da API (embora ambos ainda façam parte de um mesmo microserviço).

Mas não vira um novo microserviço?

Não. Se esses componentes compartilham o mesmo domínio, regras de negócio e banco de dados (ou gerenciam dados do mesmo contexto), ainda é um único microserviço. A delimitação principal continua sendo o “bounded context” de negócio, não a quantidade de processos implantados.


Exemplos de Cenários

1. Microserviço de Pagamentos

  • API (REST) de Pagamentos: Recebe requisições para criar uma cobrança, consultar status de pagamento etc.
  • Worker de Processamento:
    • Consome mensagens de uma fila com instruções de “capturar pagamento”, “confirmar pagamento” ou “cancelar”.
    • Pode se comunicar com gateways de pagamento externos.
  • Tarefas Agendadas (Scheduler):
    • Rotinas de reconciliação dos pagamentos diários.
    • Envios de e-mails de lembrete de pagamento atrasado.

Mesmo que a API, o worker e o scheduler sejam deployados em contêineres diferentes e escalem de forma distinta, todos fazem parte do “Microserviço de Pagamentos” e cuidam do mesmo domínio.

2. Microserviço de Catálogo de Produtos

  • API de Catalogação: Para gerenciar (CRUD) produtos, categorias, estoques, preços etc.
  • Job Worker:
    • Processa em segundo plano importações/exportações massivas de dados de produtos (por exemplo, via arquivo CSV ou integração com fornecedor).
    • Pode atualizar dados de estoque de forma assíncrona.
  • Scheduler:
    • Roda tarefas noturnas de limpeza de produtos obsoletos ou sincronização com sistemas externos.

Novamente, são vários componentes, mas todos pertencem ao domínio “Catálogo” (o que chamamos de “bounded context de catálogo”).

3. Microserviço de Notificações

  • API de Notificações: Recebe requisições para enviar e-mails, SMS, push notifications etc.
  • Worker de Envio:
    • De fato, processa em segundo plano o envio de grandes quantidades de e-mails, dispara SMS via fornecedores terceirizados e envia push notifications.
    • Trata filas e eventuais retentativas (retries) em caso de falha.
  • Scheduler de Limpeza:
    • Remove ou arquiva logs de notificações antigas.

Todos juntos formam o Microserviço de Notificações.

Como diferenciar componentes de microserviços?

  • Se o contexto de negócio é o mesmo (mesmos modelos de domínio, mesmas regras de negócio, mesmo “bounded context”), são componentes do mesmo microserviço.
  • Se lidam com contextos de negócio distintos (como “Usuários” vs. “Pagamentos”), aí sim estamos diante de microserviços diferentes.
  • Compartilhamento de banco de dados: idealmente, um microserviço é dono do seu modelo de dados (um DB ou esquema próprio). Se outro componente usa exatamente o mesmo modelo, é parte do mesmo microserviço. Se demanda lógica e dados totalmente diferentes, provavelmente justifica ser outro microserviço.
  • Visão de time/projeto: muitas vezes, cada microserviço é gerido por um time (ou parte do time) focado naquele contexto de negócio. Mesmo nesse cenário, dentro de um único microserviço podem existir várias aplicações auxiliares (API, worker, etc.).

Benefícios de projetar um microserviço com vários componentes

  1. Manutenção do código mais simples: você separa em módulos internos (ou projetos que se comunicam por filas/eventos) que tratam aspectos diferentes do mesmo problema de negócio.
  2. Independência de escalabilidade: em picos de requisições, apenas a parte de API precisa escalar; se há aumento de tarefas em segundo plano, basta escalar os workers, e assim por diante.
  3. Separação de preocupações: se cada componente foca em um tipo de “trabalho” (HTTP vs. batch vs. background tasks), fica mais fácil evoluir e dar suporte a cada um deles.

Conclusão

Um microserviço não precisa ser restrito a um único processo ou código monolítico. Ele pode (e muitas vezes deve) ter múltiplos componentes internos, cada um responsável por um tipo específico de tarefa — desde que todos estejam dentro do mesmo contexto de negócio e mantenham a coesão de domínio.

  • Não confundir: ter “várias partes” não significa que você criou “vários microserviços”.
  • que define se estamos falando de um ou mais microserviços é o contexto de negócio (bounded context), e não a quantidade de aplicações/processos.

Desse modo, quando você ou seu time quebram um microserviço em API + Worker, estão apenas criando componentes distintos para um mesmo microserviço, e não criando outro microserviço.