Arquiteturas monolíticas e de microsserviços

Concluído

A Fabrikam integrou o novo serviço de drones da empresa ao aplicativo existente. A empresa percebe que essa solução não é um bom plano para o aplicativo dela a longo prazo. O sistema tem uma arquitetura monolítica, mas o que isso significa exatamente?

O que é uma arquitetura monolítica?

Em uma arquitetura monolítica, todos os componentes de um aplicativo são colocados em uma única unidade. Normalmente, essa unidade fica restrita a uma única instância do runtime do aplicativo. Geralmente, os aplicativos tradicionais são compostos de uma interface da Web, uma camada de serviços e uma camada de dados. Em uma arquitetura monolítica, essas camadas são combinadas em uma instância do aplicativo.

Logical diagram of a monolithic architecture.

Geralmente, as arquiteturas monolíticas são soluções adequadas para aplicativos pequenos. No entanto, elas podem se tornar complicadas à medida que o aplicativo cresce. O que originalmente era um aplicativo pequeno pode rapidamente se tornar um sistema complexo e difícil de dimensionar, implantar e inovar.

Todos os serviços estão contidos em apenas uma unidade. Essa organização traz desafios à medida que seus negócios e a carga do sistema subsequente aumentam. Alguns dos desafios são:

  • dificuldade de dimensionar os serviços independentemente;
  • complexidade de desenvolver e gerenciar implantações conforme a base de código cresce, desacelerando os lançamentos e a implementação de novos recursos;
  • A arquitetura está vinculada a uma só pilha de tecnologia, limitando a inovação em novas plataformas e SDKs.
  • atualizações de esquema de dados se tornam cada vez mais difíceis.

Esses desafios podem ser superados ao analisar arquiteturas alternativas, como os microsserviços.

O que é uma arquitetura de microsserviços?

Em uma arquitetura de microsserviços, os serviços são pequenos, independentes e fracamente acoplados. Cada serviço pode ser implantado e dimensionado independentemente.

Logical diagram of a microservices architecture.

Um microsserviço é suficientemente pequeno para que uma única equipe reduzida de desenvolvedores possa escrever o código dele e mantê-lo. Como os serviços podem ser implantados de modo independente, uma equipe pode atualizar um serviço existente sem recompilar e reimplantar o aplicativo inteiro.

Normalmente, cada serviço é responsável por seus próprios dados. A estrutura de dados é isolada, de modo que as atualizações ou alterações no esquema não sejam dependentes de outros serviços. Normalmente, as solicitações de dados são manipuladas por APIs, além de fornecerem um modelo de acesso consistente e bem definido. Detalhes da implementação interna ficam ocultos de consumidores de serviços.

Como cada serviço é independente, eles podem usar pilhas de tecnologia, estruturas e SDKs diferentes. É comum ver serviços dependerem de chamadas REST para comunicação entre serviços, usando APIs bem definidas em vez de RPCs (chamadas de procedimento remoto) ou outros métodos de comunicação personalizados.

As arquiteturas de microsserviços são independentes de tecnologia, mas você verá com frequência contêineres ou tecnologias sem servidor serem usados para sua implementação. O CI/CD (implantação contínua/integração contínua) é usado frequentemente para aumentar a velocidade e a qualidade das atividades de desenvolvimento.

Benefícios de uma arquitetura de microsserviços

Por que escolher uma arquitetura de microsserviços? A arquitetura de microsserviços tem vários benefícios básicos:

  • Agilidade
  • Código pequeno, equipes pequenas
  • Combinação de tecnologias
  • Resiliência
  • Escalabilidade
  • Isolamento dos dados

Agilidade

Já que os microsserviços são implantados de forma independente, é mais fácil gerenciar correções de bugs e lançamentos de recursos. Você poderá atualizar um serviço sem reimplantar o aplicativo inteiro e, em seguida, reverter uma atualização se algo der errado. Em muitos aplicativos tradicionais, se um bug for encontrado em uma parte do aplicativo, ele poderá bloquear todo o processo de lançamento. Como resultado, novos recursos podem ser retidos até que uma correção de bug seja integrada, testada e publicada.

Código pequeno, equipes pequenas

Um microsserviço deve ser pequeno o suficiente para que possa ser criado, testado e implantado por uma única equipe de recurso. Bases de código pequenas são mais fáceis de entender. Em um aplicativo monolítico grande, as dependências de código tendem a se tornar complicadas ao longo do tempo. A adição de um novo recurso requer que se altere o código em muitos lugares. Uma arquitetura de microsserviços minimiza as dependências ao não compartilhar código ou armazenamentos de dados. Isso facilita a adição de novos recursos.

Tamanhos de equipe pequenos também promovem maior agilidade. A regra de "duas pizzas" diz que uma equipe deve ser suficientemente pequena para que duas pizzas possam alimentar a equipe. É claro que não se trata de uma métrica exata e que depende dos apetites dos membros da equipe! Mas o ponto é que grandes grupos costumam ser menos produtivos. Como a comunicação é mais lenta, a sobrecarga de gerenciamento aumenta e a agilidade diminui.

Combinação de tecnologias

As equipes podem escolher a tecnologia mais adequada para seu serviço. Eles podem usar uma combinação de pilhas de tecnologia conforme apropriado. Cada equipe pode desenvolver as tecnologias compatíveis com o serviço de modo independente. Os serviços podem usar linguagens de desenvolvimento, serviços de nuvem, SDKs diferentes e muito mais por causa dessa independência. As equipes podem escolher as melhores opções para o serviço e minimizar qualquer impacto externo para os consumidores do serviço.

Resiliência

Se um microsserviço individual ficar indisponível, isso não interromperá todo o aplicativo, desde que todos os microsserviços upstream sejam projetados para lidar corretamente com as falhas (por exemplo, implementando a interrupção de circuitos). O benefício para os usuários ou consumidores de serviço é uma experiência sempre ativa para o aplicativo.

Escalabilidade

Uma arquitetura de microsserviços permite que cada microsserviço seja dimensionado independentemente dos outros. Isso permite que você aumente subsistemas que exigem mais recursos, sem necessidade de aumentar o aplicativo inteiro. Essa organização melhora o desempenho geral do aplicativo. Ela também ajuda a minimizar os custos. Você pode adicionar mais recursos somente aos serviços que precisam deles, em vez de escalar verticalmente todo o aplicativo.

Isolamento dos dados

Uma arquitetura de microsserviços melhora a capacidade de execução de atualizações do esquema de dados, porque somente um microsserviço é afetado. Em um aplicativo monolítico, as atualizações de esquema podem se tornar desafiadoras. Partes diferentes do aplicativo podem tocar os mesmos dados, o que torna qualquer alteração no esquema arriscada. Com uma arquitetura de microsserviços, você pode atualizar um esquema, mas manter a superfície de API intacta. Os consumidores de serviço têm a mesma experiência, independentemente da arquitetura de dados subjacente.

Possíveis desafios de uma arquitetura de microsserviços

Há muitos benefícios para uma arquitetura de microsserviços, mas ela não resolve todos os problemas. Uma arquitetura de microsserviços tem seu próprio conjunto de desafios:

  • Complexidade
  • Desenvolvimento e teste
  • Falta de governança
  • Latência e congestionamento de rede
  • Integridade dos dados
  • Gerenciamento
  • Controle de versão
  • Conjunto de habilidades

Complexidade

Um aplicativo de microsserviços tem mais partes móveis que o aplicativo monolítico equivalente. Cada serviço é mais simples, mas o sistema como um todo é mais complexo. Com as ferramentas de descoberta, orquestração e automação de serviços, pode haver mais partes a serem gerenciadas no aplicativo como um todo.

Desenvolvimento e teste

Escrever um pequeno serviço que dependa de outros serviços dependentes exige uma abordagem diferente da escrita de um aplicativo tradicional monolítico ou em camadas. As ferramentas existentes não são necessariamente projetadas para funcionar com dependências de serviço. Refatorar entre limites de serviços pode ser difícil. Testar as dependências de serviço também pode ser um desafio, especialmente quando o aplicativo está evoluindo rapidamente.

Falta de governança

A abordagem descentralizada para compilar microsserviços tem vantagens, mas também pode causar problemas. Você pode acabar com muitos idiomas e estruturas diferentes que tornem difícil a manutenção do aplicativo. Pode ser útil estabelecer alguns padrões para todo o projeto, sem restringir excessivamente a flexibilidade das equipes. A necessidade de padrões uniformes se aplica especialmente a funcionalidades abrangentes, tais como registro em log e métricas.

Latência e congestionamento de rede

O uso de muitos serviços granulares pequenos pode resultar em mais comunicação entre serviços. Se a cadeia de dependências de serviço ficar muito longa, por exemplo, o serviço A chama o B, que chama o C e assim por diante, a latência adicional dessas chamadas à rede poderá se tornar um problema. Projete suas APIs com cuidado. Evite APIs excessivamente prolixas, pense em formatos de serialização e procure locais para usar padrões de comunicação assíncrona.

Integridade dos dados

Cada microsserviço é responsável pela própria persistência de dados. Assim, a consistência dos dados pode ser um desafio. Adote consistência eventual quando possível. Você também pode terminar com os dados duplicados e uma arquitetura de dados dispersa. Essa situação pode aumentar os custos de armazenamento bruto, bem como os custos do serviço de plataforma de dados com a duplicação de dados e serviço.

Gerenciamento

Ter êxito com microsserviços requer uma cultura DevOps madura. Registro em log correlacionado entre serviços pode ser desafiador. Normalmente, o registro em log deve correlacionar várias chamadas de serviço para uma operação de um único usuário.

Controle de versão

As atualizações de um serviço não devem interromper os serviços que dependem delas. Vários serviços podem ser atualizados em um determinado momento. Sem design cuidadoso, você pode ter problemas com compatibilidade com versões anteriores ou futuras. Os serviços que atrasam na adoção de novas versões de API podem aumentar os recursos e a manutenção necessários para APIs mais antigas.

Conjunto de habilidades

Os microsserviços são sistemas altamente distribuídos. Geralmente, sistemas distribuídos exigem um conjunto de habilidades diferente para serem desenvolvidos, gerenciados e mantidos adequadamente. Avalie cuidadosamente se a equipe tem as habilidades e a experiência para ser bem-sucedida. Forneça o tempo e o planejamento que suas equipes precisam para desenvolver habilidades.

Quando escolher uma arquitetura de microsserviços?

Com base em todas essas informações básicas, em que situações uma arquitetura de microsserviços é a opção mais adequada?

  • Aplicativos grandes que precisem de uma alta velocidade de lançamento.
  • Aplicativos complexos que precisam ser altamente escalonáveis.
  • Aplicativos com domínios avançados ou muitos subdomínios.
  • Uma organização que consista em pequenas equipes de desenvolvimento.