Por que usar uma abordagem de microsserviços para criar aplicativos

Para desenvolvedores de software, a fatoração de um aplicativo em partes de componentes não é nada novo. Em geral é usada uma abordagem em camadas usando um armazenamento back-end, lógica de negócios de camada intermediária e uma IU (interface do usuário) de front-end. O que mudou nos últimos anos é que os desenvolvedores estão criando aplicativos distribuídos para a nuvem.

Abaixo estão algumas necessidades de negócios em constante mudança:

  • Serviços que são construídos e operados em escala para alcançar clientes em novas regiões geográficas.
  • Entregas mais rápidas de recursos e capacidades para conseguir atender às demandas dos clientes de forma ágil.
  • Melhor utilização de recursos para reduzir os custos.

Essas necessidades comerciais estão afetando o modo como criamos os aplicativos.

Para saber mais sobre a abordagem do Azure aos microsserviços, confira Microsserviços: uma revolução nos aplicativos, proporcionada pela nuvem.

Abordagem de design monolítico versus microsserviços

Aplicações evoluem ao longo do tempo. Os aplicativos bem-sucedidos evoluem sendo úteis às pessoas. Aplicativos malsucedidos não evoluem e acabam sendo preteridos. A questão é: o quanto você sabe sobre suas necessidades atuais e quais serão no futuro? Por exemplo, digamos que esteja criando um aplicativo de relatório para um departamento. Você tem certeza de que o aplicativo se aplica somente dentro do escopo da sua empresa e de que os relatórios não serão mantidos por muito tempo. Sua escolha de abordagem é diferente de, digamos, criar um serviço de entrega de conteúdo de vídeo a dezenas de milhões de clientes.

Às vezes, lançar algo como prova de conceito é o fator determinante. Você sabe que o aplicativo pode ser reprojetado mais tarde. Não faz sentido trabalhar muito em algo que nunca será usado. Por outro lado, quando as empresas criam para a nuvem, a expectativa é de crescimento e uso. O crescimento e a escala são imprevisíveis. Queremos desenvolver um protótipo rapidamente ao mesmo tempo que sabemos que esse caminho pode nos levar ao sucesso. Essa é a abordagem de inicialização simples: compilar, medir, aprender e iterar.

Durante a época do cliente-servidor, a tendência era se concentrar na construção de aplicativos em camadas usando tecnologias específicas em cada camada. O termo aplicativo monolítico surgiu para descrever essas abordagens. As interfaces tendiam a ficar entre as camadas e um design mais rigidamente acoplado era usado entre os componentes em cada camada. Os desenvolvedores projetaram e fatoraram classes compiladas em bibliotecas e as vincularam junto em alguns arquivos executáveis e DLLs.

Existem benefícios na abordagem de design monolítico. Geralmente é mais simples de projetar e as chamadas entre os componentes são mais rápidas, pois essas chamadas são feitas através de IPC (comunicação entre processos). Além disso, todos testam um único produto, que tende a ser uma utilização mais eficiente de recursos humanos. A desvantagem é que existe um forte acoplamento entre as camadas e não é possível dimensionar os componentes individuais. Se precisar executar correções ou atualizações, é necessário esperar que as demais pessoas concluam o teste. É mais difícil ser ágil.

Os microsserviços resolvem essas desvantagens e alinham-se melhor com os requisitos de negócios anteriores. Mas eles também têm benefícios e riscos. Os benefícios dos microsserviços são que cada um normalmente encapsula uma funcionalidade de negócios mais simples, que se pode escalar horizontalmente ou verticalmente, testar, implantar e gerenciar de forma independente. Uma vantagem importante de uma abordagem de microsserviços é que as equipes são mais orientadas por cenários de negócios do que por tecnologia. Equipes menores desenvolvem um microsserviço baseado em um cenário de cliente e usam qualquer tecnologia que queiram usar.

Em outras palavras, a organização não precisa padronizar a tecnologia para manter aplicativos de microsserviço. As equipes individuais que detêm serviços podem escolher o que fizer sentido para elas com base em suas competências ou no que é mais apropriado para resolver o problema. Na prática, é preferível ter um conjunto de tecnologias recomendadas, como um determinado repositório NoSQL ou uma estrutura de aplicativo Web.

A desvantagem dos microsserviços é que se precisa gerenciar mais entidades separadas e lidar com implantações e versões mais complexas. O tráfego de rede entre os microsserviços aumenta, bem como as latências de rede correspondentes. Ter muitos serviços cliente-servidor e granulares podem causar sérios problemas de desempenho. Sem ferramentas que ajudem a mostrar essas dependências, é difícil ter uma visão de todo o sistema.

Os padrões fazem com que a abordagem de microsserviços funcione ao especificar como se comunicar e tolerar apenas o que se precisa de um serviço, em vez de usar contratos rígidos. É importante definir esses contatos antecipadamente no design, pois os serviços são atualizados de forma independente. Outra descrição cunhada para desenvolver com uma abordagem de microsserviços é "SOA (arquitetura orientada a serviços) de granulação fina".

Em sua forma mais simples, a abordagem de design com microsserviços se resume a uma federação dissociada de serviços, com alterações independentes e padrões acordados para a comunicação.

À medida que mais aplicativos em nuvem são produzidos, as pessoas estão descobrindo que essa decomposição do aplicativo global em serviços independentes, focados em cenários, é uma abordagem melhor a longo prazo.

Comparação entre abordagens de desenvolvimento de aplicativos

Service Fabric platform application development

  1. Um aplicativo monolítico contém funcionalidades específicas do domínio e é normalmente dividido em camadas funcionais, como Web, negócios e dados.

  2. Dimensiona-se um aplicativo monolítico clonando-o em vários servidores/máquinas virtuais/contêineres.

  3. Um aplicativo de microsserviço separa a funcionalidade em serviços menores separados.

  4. Essa abordagem de microsserviços pode ser dimensionada implantando cada serviço de modo independente, criando instâncias desses serviços entre servidores/máquinas virtuais/contêineres.

A criação usando a abordagem de microsserviço não é uma solução adequada para todos os projetos, ela se alinha mais aos objetivos comerciais descritos anteriormente. Começar com uma abordagem monolítica pode fazer sentido se você souber que depois terá a oportunidade de refazer o código em um design de microsserviço. Normalmente, você começa com um aplicativo monolítico e o desmembra em etapas, começando com as áreas funcionais que precisam ser mais escalonáveis ou ágeis.

Ao usar uma abordagem de microsserviços, você compõe seu aplicativo com muitos serviços pequenos. Os serviços executam em contêineres que são implantados em um cluster de máquinas. Equipes menores desenvolvem um serviço focado em um cenário e testam, criam a versão, implantam e dimensionam de forma independente cada serviço para que todo o aplicativo possa evoluir.

O que é um microsserviço?

Há diferentes definições de microsserviços. Mas a maioria dessas características de microsserviços é amplamente aceita:

  • Abrange um cenário de cliente ou comercial. Qual problema você está resolvendo?
  • Desenvolvidos por uma pequena equipe de engenharia.
  • Escritos em qualquer linguagem de programação, usando qualquer estrutura.
  • Consistem em código e opcionalmente em estado, ambos com versão, implantação e dimensionamento independentes.
  • Interagem com outros microsserviços em protocolos e interfaces bem definidos.
  • Têm nomes exclusivos (URLs) usados para determinar seus locais.
  • Permanecem consistentes e disponíveis na presença de falhas.

Resumindo:

Os aplicativos de microsserviços são compostos por serviços pequenos e focados no cliente, com controle de versão independente e escalonáveis que se comunicam entre si por meio de protocolos padrão com interfaces bem definidas.

Escritos em qualquer linguagem de programação, usando qualquer estrutura

Como desenvolvedores, queremos ser livres para escolher uma linguagem ou estrutura, dependendo de nossas habilidades ou das necessidades do serviço que estamos criando. Em alguns serviços, pode-se ter os benefícios do desempenho do C++ acima de qualquer outra coisa. Para outros, a facilidade do desenvolvimento gerenciado que se obtém do C# ou Java pode ser mais importante. Em alguns casos, talvez seja necessário usar uma específica biblioteca de terceiros, tecnologia de armazenamento de dados ou meios de expor o serviço aos clientes.

Após escolher uma tecnologia, é preciso analisar o gerenciamento operacional ou do ciclo de vida e a colocação em escala do serviço.

Permite que o código e o estado tenham versão, implantação e dimensionamento independentes

Não importa como você escreve seus microsserviços, o código e, opcionalmente, o estado, devem ser implantados, atualizados e dimensionados de forma independente. Este problemas é difícil de resolver porque se resume à escolha das tecnologias. Para a colocação em escala, é complicado entender como particionar (ou fragmentar) o código e o estado. Quando o código e o estado usam tecnologias diferentes, o que atualmente é comum, os scripts de implantação do microsserviço precisam conseguir colocá-los em escala. Essa separação também envolve agilidade e flexibilidade, para isso pode-se atualizar alguns dos microsserviços sem precisar atualizar todos de uma vez.

Voltemos à comparação entre as abordagens monolíticas e de microsserviços. Este diagrama mostra as diferenças nas abordagens para armazenar o estado:

Armazenamento de estado para as duas abordagens

Service Fabric platform state storage

A abordagem monolítica, à esquerda, tem um único banco de dados e camadas de tecnologias específicas.

A abordagem de microsserviços, à direita, tem um grafo de microsserviços interconectados em que o estado normalmente tem como escopo o microsserviço, e várias tecnologias são usadas.

Uma abordagem monolítica, o aplicativo geralmente usa um único banco de dados. A vantagem de usar um banco de dados é que ele está em um único local, o que facilita a implantação. Cada componente pode ter uma única tabela para armazenar seu estado. As equipes precisam separar estritamente estado, que é um desafio. Não há como evitar a tentação de adicionar uma coluna a uma tabela existente do cliente, fazer uma junção entre as tabelas e criar dependências na camada de armazenamento. Quando isso acontecer, não será possível dimensionar os componentes individuais.

Na abordagem dos microsserviços, cada serviço gerencia e armazena seu próprio estado. Cada serviço é responsável por dimensionar o estado e o código juntos para atender às demandas do serviço. Uma desvantagem é que, quando há necessidade de criar visualizações ou consultas dos dados de seu aplicativo, você precisa consultar vários armazenamentos de estado. Normalmente isso é resolvido com um microsserviço separado que cria uma visualização de uma coleção de microsserviços. Se precisar executar várias consultas improvisadas nos dados, considere gravar os dados de cada microsserviço em um serviço de data warehouse para análises offline.

Os microsserviços têm controle de versão. É possível que versões diferentes de um microsserviço sejam executadas lado a lado. Uma versão mais recente de um microsserviço pode falhar durante a atualização e precisa ser revertida para uma versão anterior. O controle de versão também é útil para testes A/B, em que diferentes usuários executam versões diferentes do serviço. Por exemplo, é comum atualizar um microsserviço para um conjunto específico de clientes testar a nova funcionalidade, antes de disponibilizá-lo mais amplamente.

Interage com outros microservices em protocolos e interfaces bem-definidos

Nos últimos 10 anos foram publicadas muitas informações que descrevem padrões de comunicação em arquiteturas orientadas a serviços. Em geral, a comunicação do serviço usa uma abordagem do REST com os protocolos TCP e HTTP, e XML ou JSON como formato de serialização. Do ponto de vista da interface, trata-se de tomar uma abordagem de design da Web. Mas nada o impede de usar protocolos binários ou seus próprios formatos de dados. Esteja se lembre de que as pessoas terão dificuldade em usar seus microsserviços se esses protocolos e formatos não estiverem disponíveis de forma aberta.

Tem um nome exclusivo (URL) usado para determinar sua localização

O microsserviço precisa ser endereçável independentemente do local em que está sendo executado. Se estiver pensando em computadores, e qual deles está executando um determinado microsserviço, as coisas podem dar errado rapidamente.

Da mesma forma que o DNS resolve um determinado URL para uma máquina específica, seu micros serviço precisa de um nome exclusivo para que sua localização atual seja detectável. Os microsserviços precisam de nomes endereçáveis que sejam independentes da infraestrutura em que estão sendo executados. Isso implica que há uma interação entre a maneira como seu serviço é implantado e como ele é detectado, porque deve haver um Registro do serviço. Quando um computador falha, o serviço de registro deve informar para onde o serviço foi movido.

Permanece consistente e disponível na presença de falhas

Lidar com falhas inesperadas é um dos problemas mais difíceis de se resolver, especialmente em um sistema distribuído. Grande parte do código que escrevemos como desenvolvedores é para tratar as exceções. Durante os testes, também gastamos a maior parte do tempo no tratamento das exceções. O processo envolve mais do que escrever código para tratar as falhas. O que acontece quando o computador onde o microsserviço está em execução falha? Você precisa detectar a falha, que é um problema difícil por si só. Mas você também precisa reiniciar o seu microsserviço.

Por motivos de disponibilidade, um microsserviço precisa ser resiliente a falhas e ser capaz de reiniciar em outra máquina. Além desses requisitos de resiliência, os dados não devem ser perdidos e precisam permanecer consistentes.

A resiliência é difícil de alcançar quando ocorrem falhas durante um upgrade de aplicativo. O microsserviço, trabalhando com o sistema de implantação, não precisa fazer a recuperação. Ele precisa decidir se pode continuar avançando para a versão mais recente ou reverter para uma versão anterior para manter um estado consistente. É preciso analisar algumas perguntas como se há computadores disponíveis suficientes para continuar avançando e como recuperar versões anteriores do microsserviço. Para embasar a tomada dessas decisões, é preciso que o microsserviço emita informações de integridade.

Relatórios de integridade e diagnóstico

Pode parecer óbvio, e muitas vezes é negligenciado, mas um microsserviço deve relatar sua integridade e diagnóstico. Caso contrário, há pouca percepção sobre sua integridade a partir da perspectiva das operações. Correlacionar eventos de diagnóstico em um conjunto de serviços independentes e lidar com distorções de relógio da máquina para entender a ordem dos eventos é um desafio. Da mesma forma que você interage com um micros serviço em relação a protocolos e formatos de dados acordados, é necessário padronizar como registrar eventos de integridade e diagnóstico que acabarão acabando em um armazenamento de eventos para consulta e visualização. Em uma abordagem de microsserviços, diferentes equipes precisam concordar com um único formato de log. Precisa ser uma abordagem consistente para exibir os eventos de diagnóstico no aplicativo inteiro.

Integridade é diferente de diagnóstico. Integridade significa que o microsserviço reporta seu estado atual para tomar as devidas ações. Um bom exemplo é trabalhar com mecanismos de atualização e implantação para manter a disponibilidade. Embora um serviço possa não estar íntegro no momento devido a uma falha de processo ou reinicialização do computador, o serviço ainda pode estar operacional. A última coisa de que você precisa, é piorar a situação iniciando uma atualização. A melhor abordagem é fazer uma investigação primeiro ou aguardar a recuperação do microsserviço. Os eventos de integridade de um microsserviço permitem tomar decisões bem informadas e ajudam realmente a criar serviços que recuperam a si próprios.

Diretrizes para projetar microsserviços no Azure

Visite o centro de arquitetura do Azure para obter as diretrizes sobre como projetar e criar microsserviços no Azure.

Service Fabric como uma plataforma de microsserviço

O Azure Service Fabric surgiu quando a Microsoft passou da entrega de produtos empacotados, que eram tipicamente monolíticos, para a entrega de serviços. A experiência de criar e operar serviços grandes, como o Banco de Dados SQL do Azure e o Azure Cosmos DB, modelou o Service Fabric. A plataforma evoluiu ao longo do tempo conforme mais e mais serviços a adotaram. O Service Fabric tinha que ser executado não apenas no Azure, mas também em implantações autônomas do Windows Server.

O objetivo do Service Fabric é resolver os problemas difíceis de criação e execução de um serviço, e utilizar os recursos da infraestrutura com eficiência para que as equipes possam resolver os problemas de negócios usando uma abordagem de microsserviços.

O Service Fabric ajuda você a criar aplicativos que usam uma abordagem de micros serviços, fornecendo:

  • Uma plataforma que fornece serviços do sistema para implantar, atualizar, detectar e reiniciar os serviços com falha, descobrir serviços, encaminhar mensagens, gerenciar o estado e monitorar a integridade.
  • A capacidade de implantar aplicativos executando em contêineres ou como processos. O Service Fabric é um orquestrador de contêiner e processo.
  • APIs de programação produtiva para ajudar a criar aplicativos como microsserviços: ASP.NET Core, Reliable Actors e Reliable Services. Por exemplo, você pode obter informações de integridade e diagnóstico, ou você pode tirar proveito da alta disponibilidade interna.

O Service Fabric é indiferente a como se compila o serviço, e pode ser usado com qualquer tecnologia. No entanto, ele oferece APIs de programação internas que facilitam a construção de microsserviços.

Migrando aplicativos existentes para o Service Fabric

O Service Fabric permite reutilizar o código existente, que pode então ser modernizado com novos microsserviços. Há cinco etapas para a modernização do aplicativo que podem ser iniciados e interrompidos em qualquer um dos estágios. As etapas são:

  1. Comece com um aplicativo monolítico tradicional.
  2. Migrar. Use contêineres ou executáveis de convidado para hospedar o código existente no Service Fabric.
  3. Modernizar. Adicione novos microsserviços ao código existente dos contêineres.
  4. Inovar. Quebre o aplicativo monolítico em microsserviços com base na necessidade.
  5. Transformar aplicativos em microsserviços. Transforme aplicativos monolíticos existentes ou crie novos aplicativos do zero.

Migration to microservices

Lembre-se de que você pode iniciar e parar em qualqueruma dessas etapas. Você não precisa passar para a próxima etapa.

Vamos ver exemplos de cada uma dessas etapas.

Migrar
Por dois motivos, muitas empresas estão migrando aplicativos monolíticos existentes para contêineres:

  • Redução de custos devido à consolidação e remoção de hardware existente ou a execução de aplicativos com densidade mais alta.
  • Contrato de implantação consistente entre o desenvolvimento e as operações.

As reduções de custo são simples. Na Microsoft, muitos aplicativos existentes estão sendo incluídos em contêineres, levando à economia de milhões de dólares. Uma implantação consistente é mais difícil de avaliar, mas igualmente importante. Isso significa que os desenvolvedores podem escolher as tecnologias que quiserem, mas as operações aceitarão apenas um único método para implantar e gerenciar os aplicativos. Isso evita que as operações tenham que lidar com a complexidade de oferecer suporte a diferentes tecnologias sem forçar os desenvolvedores a escolherem apenas algumas delas. Essencialmente, cada aplicativo está em contêineres em imagens de implantação independentes.

Muitas organizações param aqui. Elas já têm os benefícios dos contêineres e o Service Fabric fornece a experiência completa de gerenciamento de implantação, atualizações, controle de versão, reversões e monitoramento de integridade.

Modernizar
A modernização é a adição de novos serviços ao código existente em contêineres. Se você pretende escrever um novo código, recomenda-se dar pequenos passos e seguir o caminho dos microsserviços. Isso pode significar a adição de um novo de extremidade de API REST ou uma nova lógica de negócios. Dessa forma você inicia o processo de criação de novos microsserviços e pratica o desenvolvimento e a implantação.

Inovar
Uma abordagem de microsserviços acomoda as necessidades de negócios em mudança. Nessa etapa você precisa decidir se começa a dividir o aplicativo monolítico em serviços ou inova. Um exemplo é quando um banco de dados usado como uma fila de fluxo de trabalho se torna um gargalo de processamento. Conforme o número de solicitações de fluxo de trabalho aumenta o trabalho precisa ser distribuído para dimensionamento. Pegue a parte específica do aplicativo que não está escalando ou que precisa ser atualizada com mais frequência, e divida-a como um microsserviço e inove.

Transformar aplicativos em microsserviços
Nessa etapa, seu aplicativo está totalmente composto de (ou divididos em) microsserviços. Para alcançar esse ponto, você fez o percurso dos microsserviços. Você pode iniciar aqui, mas fazer isso sem uma plataforma de microsserviços para ajudá-lo é um grande investimento.

Os microsserviços são ideais para meu aplicativo?

Talvez. Na Microsoft, à medida que mais equipes começaram a construir para a nuvem por motivos comerciais, muitas delas perceberam os benefícios de adotar uma abordagem semelhante ao microsserviço. O Bing, por exemplo, vem usando microsserviços há anos. Para as outras equipes, a abordagem dos microsserviços foi nova. As equipes descobriram que havia problemas difíceis de resolver fora de suas principais áreas de capacidade. É por isso que o Service Fabric ganhou força como a tecnologia preferida para a criação de serviços.

O objetivo do Service Fabric é reduzir as complexidades da criação de aplicativos de microsserviços para que você não precise passar por tantos reprojetos dispendiosos. Comece pequeno, dimensione quando necessário, descontinue serviços, adicione novos e evolua com o uso do cliente. Também sabemos que há muitos outros problemas que ainda precisam ser resolvidos para tornar os microsserviços mais acessíveis à maioria dos desenvolvedores. Os contêineres e o modelo de programação de ator são exemplos de pequenas etapas nessa direção. Temos certeza de que mais inovações surgirão para facilitar a abordagem microsserviços.

Próximas etapas