Arquitetura de microserviços

Janeiro 10, 2020

Você está desenvolvendo um aplicativo corporativo do servidor. Ele deve suportar uma variedade de clientes diferentes, incluindo navegadores de desktop, navegadores móveis e aplicativos móveis nativos. O aplicativo também pode expor uma API para terceiros consumirem. Também pode se integrar a outros aplicativos por meio de serviços da web ou de um intermediário de mensagens. O aplicativo manipula solicitações (solicitações e mensagens HTTP) executando a lógica de negócios; acessando um banco de dados; troca de mensagens com outros sistemas; e retornando uma resposta HTML / JSON / XML. Existem componentes lógicos correspondentes a diferentes áreas funcionais do aplicativo.

Problema

Qual é a arquitetura de deployment da aplicação?

Forças

  • Há uma equipe de desenvolvedores trabalhando no aplicativo
  • Novos membros da equipe devem se tornar rapidamente produtivos
  • O aplicativo deve ser fácil de entender e modificar
  • Você deseja praticar a implantação contínua do aplicativo
  • Você deve executar várias instâncias do aplicativo em várias máquinas para satisfazer os requisitos de escalabilidade e disponibilidade
  • Você deseja aproveitar as tecnologias emergentes (estruturas, linguagens de programação etc.)

Solução

Defina uma arquitetura que estrutura o aplicativo como um conjunto de serviços colaborativos fracamente acoplados. Essa abordagem corresponde ao eixo Y do cubo de escala. Cada serviço é:

  • Altamente manutenível e testável - permite desenvolvimento e implantação rápidos e frequentes
  • Acoplado livremente a outros serviços - permite que uma equipe trabalhe de forma independente a maior parte do tempo em seus serviços, sem ser impactada por alterações em outros serviços e sem afetar outros serviços
  • Implantável independentemente - permite que uma equipe implante seu serviço sem precisar se coordenar com outras equipes
  • Capaz de ser desenvolvido por uma equipe pequena - essencial para alta produtividade, evitando o alto chefe de comunicação de equipes grandes
Os serviços se comunicam usando protocolos síncronos como HTTP / REST ou protocolos assíncronos como AMQP. Os serviços podem ser desenvolvidos e implantados independentemente um do outro. Cada serviço possui seu próprio banco de dados para ser dissociado de outros serviços. A consistência dos dados entre serviços é mantida usando o padrão Saga.

Exemplos

Aplicação fictícia de e-commerce

Vamos imaginar que você esteja criando um aplicativo de comércio eletrônico que recebe pedidos dos clientes, verifica o estoque e o crédito disponível e os envia. O aplicativo consiste em vários componentes, incluindo o StoreFrontUI, que implementa a interface do usuário, além de alguns serviços de back-end para verificação de crédito, manutenção de estoque e envio de pedidos. O aplicativo consiste em um conjunto de serviços.

0

Contexto resultante

Benefícios

Esta solução tem muitos benefícios:

  • Permite a entrega e implantação contínuas de aplicativos grandes e complexos.
  •                                    
  • Manutenção melhorada - cada serviço é relativamente pequeno e, portanto, mais fácil de entender e alterar
  • Melhor testabilidade - os serviços são menores e mais rápidos para testar
  •                                    
  • Melhor capacidade de implantação - os serviços podem ser implantados independentemente

Ele permite que você organize o esforço de desenvolvimento em torno de várias equipes autônomas. Cada equipe (denominada duas pizzas) possui e é responsável por um ou mais serviços. Cada equipe pode desenvolver, testar, implantar e dimensionar seus serviços independentemente de todas as outras equipes.

                                   

Cada microsserviço é relativamente pequeno:

  • Mais fácil para um desenvolvedor entender
  •                                    
  • O IDE é mais rápido, tornando os desenvolvedores mais produtivos
  •                                    
  • O aplicativo inicia mais rápido, o que torna os desenvolvedores mais produtivos e acelera as implantações
  •                                    
  • Melhor isolamento de falhas. Por exemplo, se houver um vazamento de memória em um serviço, apenas esse serviço será afetado. Os outros serviços continuarão a lidar com solicitações. Em comparação, um componente que se comporta mal de uma arquitetura monolítica pode derrubar todo o sistema.
  •                                    

Elimina qualquer compromisso de longo prazo com uma pilha de tecnologia. Ao desenvolver um novo serviço, você pode escolher uma nova pilha de tecnologia. Da mesma forma, ao fazer grandes alterações em um serviço existente, você pode reescrevê-lo usando uma nova pilha de tecnologia.

Desvantagens

Esta solução tem algumas desvantagens:

Os desenvolvedores devem lidar com a complexidade adicional de criar um sistema distribuído:

  • Os desenvolvedores devem implementar o mecanismo de comunicação entre serviços e lidar com falhas parciais
  •                                    
  • Implementar solicitações que abrangem vários serviços é mais difícil
  •                                    
  • Testar as interações entre serviços é mais difícil
  •                                    
  • A implementação de solicitações que abrangem vários serviços requer uma coordenação cuidadosa entre as equipes
  •                                    
  • As ferramentas / IDEs para desenvolvedores são orientadas para a criação de aplicativos monolíticos e não fornecem suporte explícito ao desenvolvimento de aplicativos distribuídos.
  •                                    
  • Complexidade de implantação. Na produção, há também a complexidade operacional de implantar e gerenciar um sistema composto por muitos serviços diferentes.
  •                                    
  • Maior consumo de memória. A arquitetura de microsserviço substitui N instâncias de aplicativos monolíticos por instâncias de serviços NxM. Se cada serviço for executado em sua própria JVM (ou equivalente), o que geralmente é necessário para isolar as instâncias, haverá uma sobrecarga de M vezes o tempo de execução da JVM. Além disso, se cada serviço for executado em sua própria VM (por exemplo, instância EC2), como é o caso da Netflix, a sobrecarga será ainda maior.

Problemas

Há muitos problemas que você deve resolver.

Quando usar a arquitetura de microsserviço?

Um desafio ao usar essa abordagem é decidir quando faz sentido usá-la. Ao desenvolver a primeira versão de um aplicativo, geralmente você não tem os problemas que essa abordagem resolve. Além disso, o uso de uma arquitetura elaborada e distribuída desacelerará o desenvolvimento. Esse pode ser um grande problema para empresas iniciantes cujo maior desafio geralmente é como evoluir rapidamente o modelo de negócios e o aplicativo que o acompanha. O uso de divisões no eixo Y pode tornar muito mais difícil a iteração rápida. Mais tarde, no entanto, quando o desafio é como escalar e você precisa usar a decomposição funcional, as dependências emaranhadas podem dificultar a decomposição do aplicativo monolítico em um conjunto de serviços.

Como decompor o aplicativo em serviços?

Outro desafio é decidir como particionar o sistema em microsserviços. Isso é muito uma arte, mas existem várias estratégias que podem ajudar:

  • Decomponha por capacidade de negócios e defina serviços correspondentes às capacidades de negócios.
  •                                    
  • Decompor por subdomínio de design controlado por domínio.
  •                                    
  • Decomponha por verbo ou caso de uso e defina serviços responsáveis por ações específicas. por exemplo. um serviço de remessa responsável pelo envio de pedidos completos.
  • Decomponha por substantivos ou recursos, definindo um serviço responsável por todas as operações em entidades / recursos de um determinado tipo. por exemplo. um serviço de conta responsável pelo gerenciamento de contas de usuário.

Idealmente, cada serviço deve ter apenas um pequeno conjunto de responsabilidades. (Tio) Bob Martin fala sobre o design de classes usando o Princípio de Responsabilidade Única (SRP). O SRP define a responsabilidade de uma classe como um motivo para mudar e afirma que uma classe deve ter apenas um motivo para mudar. Também faz sentido aplicar o SRP ao design de serviço.

Outra analogia que ajuda no design de serviços é o design dos utilitários Unix. O Unix fornece um grande número de utilitários como grep, cat e find. Cada utilitário faz exatamente uma coisa, geralmente excepcionalmente bem, e pode ser combinado com outros utilitários usando um script de shell para executar tarefas complexas.

Como manter a consistência dos dados?

Para garantir um acoplamento flexível, cada serviço possui seu próprio banco de dados. Manter a consistência dos dados entre os serviços é um desafio, porque as transações de confirmação / distribuição em 2 fases não são uma opção para muitos aplicativos. Um aplicativo deve usar o padrão Saga. Um serviço publica um evento quando seus dados são alterados. Outros serviços consomem esse evento e atualizam seus dados. Existem várias maneiras de atualizar dados de forma confiável e publicar eventos, incluindo o fornecimento de eventos e o final do log de transações.

Como implementar consultas?

Outro desafio é implementar consultas que precisam recuperar dados pertencentes a vários serviços

Padrões relacionados

Existem muitos padrões relacionados ao padrão de microsserviços. A arquitetura monolítica é uma alternativa à arquitetura de microsserviço. Os outros padrões abordam os problemas que você encontrará ao aplicar a arquitetura de microsserviço.

0

Usos conhecidos

A maioria dos sites de larga escala, incluindo Netflix, Amazon e eBay, evoluiu de uma arquitetura monolítica para uma arquitetura de microsserviço.

O Netflix, um serviço de streaming de vídeo muito popular responsável por até 30% do tráfego da Internet, possui uma arquitetura orientada a serviços em larga escala. Eles gerenciam mais de um bilhão de chamadas por dia para a API de streaming de vídeo de mais de 800 tipos diferentes de dispositivos. Cada chamada de API atende a uma média de seis chamadas para serviços de back-end.

A Amazon.com originalmente possuía uma arquitetura de duas camadas. Para escalar, eles migraram para uma arquitetura orientada a serviços que consiste em centenas de serviços de back-end. Vários aplicativos chamam esses serviços, incluindo os que implementam o site Amazon.com e a API de serviço web. O aplicativo do site Amazon.com chama 100-150 serviços para obter os dados usados para criar uma página da web.

O site de leilões ebay.com também evoluiu de uma arquitetura monolítica para uma arquitetura orientada a serviços. A camada do aplicativo consiste em vários aplicativos independentes. Cada aplicativo implementa a lógica de negócios para uma área de função específica, como compra ou venda. Cada aplicativo usa divisões no eixo X e alguns aplicativos, como a pesquisa, usam divisões no eixo Z. O Ebay.com também aplica uma combinação de dimensionamento dos estilos X, Y e Z à camada do banco de dados.