Uma arquitetura de microsserviços consiste numa coleção de pequenos serviços autónomos. Cada serviço é autônomo e deve implementar um único recurso de negócios dentro de um contexto limitado. Um contexto delimitado é uma divisão natural dentro de uma empresa e fornece um limite explícito dentro do qual existe um modelo de domínio.
O que são os microsserviços?
Os microsserviços são serviços pequenos, independentes e relativamente interligados. Uma única pequena equipa de programadores consegue escrever e tratar da manutenção de um serviço.
Cada serviço é um código base separado, que pode ser gerido por uma equipa de desenvolvimento pequena.
Os serviços podem ser implementados de forma independente. Uma equipa pode atualizar um serviço existente sem reconstruir e reimplementar toda a aplicação.
Os serviços são responsáveis pela persistência dos seus próprios dado ou estado externo. Isto é diferente do modelo tradicional, em que uma camada de dados separada processa a persistência dos dados.
Os serviços comunicam entre si através de APIs bem definidas. Os detalhes internos da implementação de cada serviço estão ocultos de outros serviços.
Suporta programação poliglota. Por exemplo, os serviços não precisam compartilhar a mesma pilha de tecnologia, bibliotecas ou estruturas.
Além dos próprios serviços, alguns outros componentes estão presentes numa arquitetura de microsserviços típica:
Gestão/orquestração. Este componente é responsável por colocar os serviços em nós, identificando falhas, reequilibrando os serviços nos nós e assim sucessivamente. Normalmente, este componente é uma tecnologia pronta a utilizar, como o Kubernetes, em vez de ser algo personalizado.
Gateway de API. O gateway da API é o ponto de entrada para os clientes. Em vez de chamarem serviços diretamente, os clientes chamam o gateway de API, o qual reencaminha a chamada para os serviços adequados no back-end.
As vantagens de utilizar um gateway de API incluem:
Dissocia os clientes dos serviços. Pode dar uma versão dos serviços e refatorizá-los, sem ser necessário atualizar todos os clientes.
Os serviços podem utilizar protocolos de mensagens que não são adequados para a Web, como o AMQP.
O Gateway da API pode realizar outras funções transversais, como a autenticação, o registo, a terminação de SSL e o balanceamento de carga.
Políticas prontas para uso, como para limitação, armazenamento em cache, transformação ou validação.
Benefícios
Agilidade. Como os microsserviços são implementados de forma independente, pode gerir a correção de erros e o lançamento de funcionalidades com mais facilidade. Pode atualizar um serviço sem implementar novamente toda a aplicação e reverter uma atualização caso algo corra mal. Em muitas aplicações tradicionais, se for encontrado um erro numa parte da aplicação, esse erro poderá bloquear todo o processo de lançamento da versão. Novos recursos podem ficar retidos aguardando que uma correção de bug seja integrada, testada e publicada.
Equipas pequenas e direcionadas. Um microsserviço deve ser pequeno ao ponto de ser possível que uma única equipa consiga criá-lo, testá-lo e implementá-lo. As equipas mais pequenas promovem uma maior agilidade. As equipas grandes tendem a ser menos produtivas, porque a comunicação é mais demorada, a despesa de gestão aumenta e a agilidade diminui.
Base de código pequena. Em um aplicativo monolítico, há uma tendência ao longo do tempo para as dependências de código se tornarem emaranhadas. Adicionar um novo recurso requer tocar no código em muitos lugares. Como os microsserviços não partilham código nem arquivos de dados, a arquitetura de microsserviços minimiza as dependências, o que torna mais fácil adicionar novas funcionalidades.
Misto de tecnologias. As equipas podem escolher a tecnologia mais adequada ao respetivo serviço, através da utilização de várias tecnologias diferentes, conforme as necessidades.
Isolamento de falhas. Se um microsserviço individual ficar indisponível, ele não interromperá todo o aplicativo, desde que todos os microsserviços upstream sejam projetados para lidar com falhas corretamente. Por exemplo, você pode implementar o padrão Disjuntor ou projetar sua solução para que os microsserviços se comuniquem entre si usando padrões de mensagens assíncronas.
Escalabilidade. Os serviços podem ser dimensionados independentemente, o que lhe permite ampliar os subsistemas que necessitem de mais recursos sem que, para isso, tenha de aumentar horizontalmente toda a aplicação. Usando um orquestrador como o Kubernetes, você pode empacotar uma maior densidade de serviços em um único host, o que permite uma utilização mais eficiente dos recursos.
Isolamento de dados. É muito mais fácil fazer atualizações de esquema porque apenas é afetado um único microsserviço. Em um aplicativo monolítico, as atualizações de esquema podem se tornar muito desafiadoras, porque diferentes partes do aplicativo podem tocar nos mesmos dados, tornando arriscadas quaisquer alterações no esquema.
Desafios
Os microsserviços não trazem apenas benefícios. Eis alguns dos desafios a considerar antes de adotar uma arquitetura de microsserviços.
Complexidade. Uma aplicação de microsserviços tem mais partes em movimento do que a aplicação monolítica equivalente. Cada serviço é mais simples, mas o sistema como um todo é mais complexo.
Desenvolvimento e teste. Escrever um pequeno serviço que depende de outros serviços dependentes requer uma abordagem diferente de escrever um aplicativo monolítico tradicional ou em camadas. As ferramentas existentes não foram sempre concebidas para funcionar com as dependências do serviço. Refatorizar através de limites de serviço pode ser difícil. Testar as dependências do serviço também é particularmente desafiante, especialmente quando a aplicação está a evoluir rapidamente.
Falta de governação. A abordagem descentralizada da criação de microsserviços tem vantagens, mas também pode provocar problemas. Pode ficar com tantas linguagens e estruturas diferentes que se torna difícil gerir a aplicação. Poderá ser útil implementar alguns padrões em todo o projeto, sem restringir excessivamente a flexibilidade das equipas. Isto aplica-se especialmente a funcionalidades transversais, como o registo.
Congestionamento e latência de rede. A utilização de muitos serviços pequenos e granulares pode originar uma maior comunicação entre serviços. Além disso, se a cadeia de dependências de serviços ficar muito longa (o serviço A chama o serviço B, que chama o C, etc.), a latência adicional pode tornar-se um problema. Terá de estruturar as APIs cuidadosamente. Evite APIs excessivamente tagarelas, pense em formatos de serialização e procure locais para usar padrões de comunicação assíncronos, como nivelamento de carga baseado em fila.
Integridade dos dados. Cada microsserviço é responsável pela sua própria persistência de dados. Como resultado, a consistência de dados em vários serviços pode ser um desafio. Serviços diferentes persistem dados em momentos diferentes, usando tecnologias diferentes e com níveis potencialmente diferentes de sucesso. Quando mais de um microsserviço está envolvido na persistência de uma data nova ou alterada, é improvável que a alteração completa dos dados possa ser considerada uma transação ACID. Em vez disso, a técnica está mais alinhada com BASE (Basicamente Disponível, Estado suave e Eventualmente consistente). Adote a consistência eventual sempre que possível.
Gestão. O êxito dos microsserviços requer uma cultura DevOps madura. O registo correlacionado entre serviços pode ser um desafio. Normalmente, o registo tem de correlacionar múltiplas chamadas de serviço para uma única operação de utilizador.
Controlo de versões. As atualizações de um serviço não podem interromper os serviços que dependem dele. Múltiplos serviços poderiam ser atualizados num determinado momento pelo que, sem uma estrutura cuidadosa, poderia ter problemas de retrocompatibilidade ou compatibilidade com as versões seguintes.
Competências. Os microsserviços são sistemas altamente distribuídos. Avalie cuidadosamente se a equipa tem as competências e a experiência para o êxito.
Melhores práticas
Serviços de modelo em todo o domínio empresarial.
Decentralize tudo. Equipas individuais são responsáveis pela conceção e criação de serviços. Evite a partilha de código ou esquemas de dados.
O armazenamento de dados deve ser privado para o serviço que detém os dados. Utilize o melhor armazenamento para cada serviço e tipo de dados.
Os serviços comunicam através de APIs devidamente estruturadas. Evite a fuga de detalhes da implementação. As APIs deve modelar o domínio, não a implementação interna do serviço.
Evite o acoplamento entre serviços. As causas de acoplamento incluem esquemas de bases de dados partilhados e protocolos de comunicação rígidos.
Não descarregue as preocupações transversais, como a autenticação e a terminação SSL, para o gateway.
Mantenha os conhecimentos do domínio fora do gateway. O gateway deve processar e encaminhar os pedidos de cliente sem qualquer conhecimento das regras de negócio ou lógica de domínio. Caso contrário, o gateway torna-se uma dependência e pode provocar o acoplamento entre serviços.
Os serviços devem ter um acoplamento alargado e uma coesão altamente funcional. As funções que se prevê serem alteradas em conjunto devem ser compactadas e implementadas em conjunto. Se residirem em serviços separados, esses serviços acabam por ser estreitamente acoplados, porque uma alteração de um serviço irá necessitar de atualizar o outro serviço. A comunicação excessivamente ativa entre dois serviços pode ser um sintoma de acoplamento estreito e baixa coesão.
Isole as falhas. Utilize as estratégias de resiliência para impedir falhas em cascata dentro de um serviço. Consulte Padrões de resiliência e Projetando aplicativos confiáveis.
Próximos passos
Para obter documentação de orientação detalhada sobre como criar uma arquitetura de microsserviços no Azure, veja Estruturar, criar e utilizar microsserviços no Azure.