Editor – Esta série de artigos em sete partes está agora completa:
Você também pode baixar o conjunto completo de artigos, além de informações sobre a implementação de microsserviços usando o NGINX Plus, como um e-book – Microsserviços: Do design à implantação . E veja nossa série sobre a Arquitetura de Referência de Microsserviços e a página Soluções de Microsserviços .
Este é o sexto artigo de uma série sobre criação de aplicativos com microsserviços. O primeiro artigo apresenta o padrão de arquitetura de microsserviços e discute os benefícios e desvantagens do uso de microsserviços. Os artigos a seguir discutem diferentes aspectos da arquitetura de microsserviços: uso de um API Gateway , comunicação entre processos , descoberta de serviços e gerenciamento de dados orientado a eventos . Neste artigo, analisamos estratégias para implantação de microsserviços.
Implantar um aplicativo monolítico significa executar várias cópias idênticas de um único aplicativo, geralmente grande. Normalmente, você provisiona N servidores (físicos ou virtuais) e executa M instâncias do aplicativo em cada um. A implantação de um aplicativo monolítico nem sempre é totalmente direta, mas é muito mais simples do que implantar um aplicativo de microsserviços.
Um aplicativo de microsserviços consiste em dezenas ou até centenas de serviços. Os serviços são escritos em diversas linguagens e estruturas. Cada um é um miniaplicativo com seus próprios requisitos específicos de implantação, recursos, dimensionamento e monitoramento. Por exemplo, você precisa executar um certo número de instâncias de cada serviço com base na demanda desse serviço. Além disso, cada instância de serviço deve receber recursos apropriados de CPU, memória e E/S. O que é ainda mais desafiador é que, apesar dessa complexidade, a implantação de serviços deve ser rápida, confiável e econômica.
Existem alguns padrões diferentes de implantação de microsserviços. Vamos primeiro dar uma olhada no padrão Multiple Service Instances per Host.
Uma maneira de implantar seus microsserviços é usar o padrão Várias Instâncias de Serviço por Host . Ao usar esse padrão, você provisiona um ou mais hosts físicos ou virtuais e executa várias instâncias de serviço em cada um. De muitas maneiras, essa é a abordagem tradicional para implantação de aplicativos. Cada instância de serviço é executada em uma porta conhecida em um ou mais hosts. As máquinas host são comumente tratadas como animais de estimação .
O diagrama a seguir mostra a estrutura desse padrão.
Há algumas variantes desse padrão. Uma variante é que cada instância de serviço seja um processo ou um grupo de processos. Por exemplo, você pode implantar uma instância de serviço Java como um aplicativo web em um servidor Apache Tomcat . Uma instância de serviço Node.js pode consistir em um processo pai e um ou mais processos filho.
A outra variante desse padrão é executar várias instâncias de serviço no mesmo processo ou grupo de processos. Por exemplo, você pode implantar vários aplicativos da web Java no mesmo servidor Apache Tomcat ou executar vários pacotes OSGI no mesmo contêiner OSGI.
O padrão de múltiplas instâncias de serviço por host tem vantagens e desvantagens. Um grande benefício é que o uso de recursos é relativamente eficiente. Várias instâncias de serviço compartilham o servidor e seu sistema operacional. É ainda mais eficiente se um processo ou grupo de processos executar várias instâncias de serviço, por exemplo, vários aplicativos da Web compartilhando o mesmo servidor Apache Tomcat e JVM.
Outro benefício desse padrão é que a implantação de uma instância de serviço é relativamente rápida. Basta copiar o serviço para um host e iniciá-lo. Se o serviço for escrito em Java, você copia um arquivo JAR ou WAR. Para outras linguagens, como Node.js ou Ruby, você copia o código-fonte. Em ambos os casos, o número de bytes copiados pela rede é relativamente pequeno.
Além disso, devido à falta de custos indiretos, iniciar um serviço geralmente é muito rápido. Se o serviço for um processo próprio, basta iniciá-lo. Caso contrário, se o serviço for uma das várias instâncias em execução no mesmo processo de contêiner ou grupo de processos, você o implantará dinamicamente no contêiner ou reiniciará o contêiner.
Apesar de seu apelo, o padrão de múltiplas instâncias de serviço por host tem algumas desvantagens significativas. Uma grande desvantagem é que há pouco ou nenhum isolamento das instâncias de serviço, a menos que cada instância de serviço seja um processo separado. Embora você possa monitorar com precisão a utilização de recursos de cada instância de serviço, não é possível limitar os recursos que cada instância usa. É possível que uma instância de serviço com comportamento inadequado consuma toda a memória ou CPU do host.
Não há isolamento algum se várias instâncias de serviço forem executadas no mesmo processo. Todas as instâncias podem, por exemplo, compartilhar o mesmo heap da JVM. Uma instância de serviço com comportamento inadequado poderia facilmente interromper os outros serviços em execução no mesmo processo. Além disso, você não tem como monitorar os recursos usados por cada instância de serviço.
Outro problema significativo com essa abordagem é que a equipe de operações que implanta um serviço precisa conhecer os detalhes específicos de como fazê-lo. Os serviços podem ser escritos em diversas linguagens e estruturas, portanto, há muitos detalhes que a equipe de desenvolvimento deve compartilhar com as operações. Essa complexidade aumenta o risco de erros durante a implantação.
Como você pode ver, apesar de sua familiaridade, o padrão Multiple Service Instances per Host tem algumas desvantagens significativas. Vejamos agora outras maneiras de implantar microsserviços que evitam esses problemas.
Outra maneira de implantar seus microsserviços é o padrão Instância de Serviço por Host . Ao usar esse padrão, você executa cada instância de serviço isoladamente em seu próprio host. Existem duas especializações diferentes desse padrão: Instância de serviço por máquina virtual e instância de serviço por contêiner.
Ao usar o padrão Service Instance per Virtual Machine , você empacota cada serviço como uma imagem de máquina virtual (VM), como uma Amazon EC2 AMI . Cada instância de serviço é uma VM (por exemplo, uma instância EC2) que é iniciada usando essa imagem de VM. O diagrama a seguir mostra a estrutura deste padrão:
Esta é a principal abordagem usada pela Netflix para implantar seu serviço de streaming de vídeo. A Netflix empacota cada um dos seus serviços como uma EC2 AMI usando o Aminator . Cada instância de serviço em execução é uma instância EC2.
Há uma variedade de ferramentas que você pode usar para construir suas próprias VMs. Você pode configurar seu servidor de integração contínua (CI) (por exemplo, Jenkins ) para invocar o Aminator para empacotar seus serviços como um EC2 AMI. Packer.io é outra opção para criação automatizada de imagens de VM. Ao contrário do Aminator, ele suporta uma variedade de tecnologias de virtualização, incluindo EC2, DigitalOcean, VirtualBox e VMware.
A empresa Boxfuse tem uma maneira atraente de criar imagens de VM, que supera as desvantagens das VMs que descrevo abaixo. O Boxfuse empacota seu aplicativo Java como uma imagem de VM mínima. Essas imagens são rápidas de criar, inicializam rapidamente e são mais seguras, pois expõem uma superfície de ataque limitada.
A empresa CloudNative tem o Bakery, uma oferta SaaS para criação de AMIs EC2. Você pode configurar seu servidor de CI para invocar o Bakery após os testes do seu microsserviço serem aprovados. A Bakery então empacota seu serviço como uma AMI. Usar uma oferta SaaS como a Bakery significa que você não precisa desperdiçar tempo valioso configurando a infraestrutura de criação de AMI.
O padrão Instância de Serviço por Máquina Virtual tem vários benefícios. Um grande benefício das VMs é que cada instância de serviço é executada em completo isolamento. Ele tem uma quantidade fixa de CPU e memória e não pode roubar recursos de outros serviços.
Outro benefício de implantar seus microsserviços como VMs é que você pode aproveitar uma infraestrutura de nuvem madura. Nuvens como a AWS fornecem recursos úteis, como balanceamento de carga e dimensionamento automático.
Outro grande benefício de implantar seu serviço como uma VM é que ele encapsula a tecnologia de implementação do seu serviço. Depois que um serviço é empacotado como uma VM, ele se torna uma caixa preta. A API de gerenciamento da VM se torna a API para implantação do serviço. A implantação se torna muito mais simples e confiável.
No entanto, o padrão Instância de Serviço por Máquina Virtual tem algumas desvantagens. Uma desvantagem é a utilização menos eficiente dos recursos. Cada instância de serviço tem a sobrecarga de uma VM inteira, incluindo o sistema operacional. Além disso, em um IaaS público típico, as VMs vêm em tamanhos fixos e é possível que a VM seja subutilizada.
Além disso, um IaaS público normalmente cobra por VMs, independentemente de elas estarem ocupadas ou ociosas. Um IaaS como o AWS fornece dimensionamento automático, mas é difícil reagir rapidamente a mudanças na demanda . Consequentemente, muitas vezes você precisa provisionar VMs em excesso, o que aumenta o custo de implantação.
Outra desvantagem dessa abordagem é que a implantação de uma nova versão de um serviço geralmente é lenta. As imagens de VM geralmente são lentas para serem criadas devido ao seu tamanho. Além disso, as VMs geralmente são lentas para instanciar, novamente por causa de seu tamanho. Além disso, um sistema operacional normalmente leva algum tempo para inicializar. Observe, no entanto, que isso não é universalmente verdadeiro, pois existem VMs leves, como as criadas pela Boxfuse.
Outra desvantagem do padrão Instância de Serviço por Máquina Virtual é que normalmente você (ou outra pessoa na sua organização) é responsável por grande parte do trabalho pesado e indiferenciado. A menos que você use uma ferramenta como o Boxfuse, que cuida da sobrecarga de criação e gerenciamento de VMs, a responsabilidade é sua. Essa atividade necessária, mas demorada, distrai você do seu negócio principal.
Vamos agora dar uma olhada em uma maneira alternativa de implantar microsserviços que é mais leve, mas ainda tem muitos dos benefícios das VMs.
Quando você usa o padrão Instância de serviço por contêiner , cada instância de serviço é executada em seu próprio contêiner. Os contêineres são um mecanismo de virtualização no nível do sistema operacional . Um contêiner consiste em um ou mais processos em execução em uma sandbox. Da perspectiva dos processos, eles têm seu próprio namespace de porta e sistema de arquivos raiz. Você pode limitar os recursos de memória e CPU de um contêiner. Algumas implementações de contêineres também têm limitação de taxa de E/S. Exemplos de tecnologias de contêiner incluem Docker e Solaris Zones .
O diagrama a seguir mostra a estrutura deste padrão:
Para usar esse padrão, você empacota seu serviço como uma imagem de contêiner. Uma imagem de contêiner é uma imagem de sistema de arquivos que consiste nos aplicativos e bibliotecas necessários para executar o serviço. Algumas imagens de contêiner consistem em um sistema de arquivos raiz Linux completo. Outros são mais leves. Para implantar um serviço Java, por exemplo, você cria uma imagem de contêiner contendo o tempo de execução Java, talvez um servidor Apache Tomcat e seu aplicativo Java compilado.
Depois de empacotar seu serviço como uma imagem de contêiner, você inicia um ou mais contêineres. Normalmente, você executa vários contêineres em cada host físico ou virtual. Você pode usar um gerenciador de cluster como o Kubernetes ou o Marathon para gerenciar seus contêineres. Um gerenciador de cluster trata os hosts como um pool de recursos. Ele decide onde colocar cada contêiner com base nos recursos exigidos pelo contêiner e nos recursos disponíveis em cada host.
O padrão Instância de Serviço por Contêiner tem vantagens e desvantagens. Os benefícios dos contêineres são semelhantes aos das VMs. Eles isolam suas instâncias de serviço umas das outras. Você pode monitorar facilmente os recursos consumidos por cada contêiner. Além disso, assim como as VMs, os contêineres encapsulam a tecnologia usada para implementar seus serviços. A API de gerenciamento de contêineres também serve como API para gerenciar seus serviços.
No entanto, diferentemente das VMs, os contêineres são uma tecnologia leve. Imagens de contêiner geralmente são muito rápidas de criar. Por exemplo, no meu laptop, leva apenas 5 segundos para empacotar um aplicativo Spring Boot como um contêiner Docker. Os contêineres também iniciam muito rapidamente, pois não há um longo mecanismo de inicialização do sistema operacional. Quando um contêiner é iniciado, o que é executado é o serviço.
Existem algumas desvantagens no uso de contêineres. Embora a infraestrutura de contêineres esteja amadurecendo rapidamente, ela não é tão madura quanto a infraestrutura para VMs. Além disso, os contêineres não são tão seguros quanto as VMs, pois os contêineres compartilham o kernel do SO host entre si.
Outra desvantagem dos contêineres é que você é responsável pelo trabalho pesado e indiferenciado de administrar as imagens dos contêineres. Além disso, a menos que você esteja usando uma solução de contêiner hospedado, como o Google Container Engine ou o Amazon EC2 Container Service (ECS), você deverá administrar a infraestrutura do contêiner e, possivelmente, a infraestrutura de VM na qual ele é executado.
Além disso, os contêineres geralmente são implantados em uma infraestrutura que tem preços por VM. Consequentemente, conforme descrito anteriormente, você provavelmente incorrerá no custo extra de provisionamento excessivo de VMs para lidar com picos de carga.
Curiosamente, a distinção entre contêineres e VMs provavelmente ficará mais tênue. Como mencionado anteriormente, as VMs do Boxfuse são rápidas de criar e iniciar. O projeto Clear Containers visa criar VMs leves. [Editor – Conforme anunciado em dezembro de 2017, o desenvolvimento do Clear Containers agora continua no projeto de código aberto Kata Containers .] Há também um interesse crescente em unikernels . A Docker, Inc. adquiriu recentemente a Unikernel Systems.
Há também o conceito mais novo e cada vez mais popular de implantação sem servidor, que é uma abordagem que contorna a questão de ter que escolher entre implantar serviços em contêineres ou VMs. Vamos dar uma olhada nisso a seguir.
O AWS Lambda é um exemplo de tecnologia de implantação sem servidor. Ele suporta serviços Java, Node.js e Python. Para implantar um microsserviço, você o empacota como um arquivo ZIP e o carrega no AWS Lambda. Você também fornece metadados, que entre outras coisas especificam o nome da função que é invocada para manipular uma solicitação (também conhecida como evento). O AWS Lambda executa automaticamente instâncias suficientes do seu microsserviço para lidar com solicitações. Você é simplesmente cobrado por cada solicitação com base no tempo gasto e na memória consumida. É claro que o diabo está nos detalhes e você verá em breve que o AWS Lambda tem limitações. Mas a noção de que nem você, como desenvolvedor, nem ninguém na sua organização precisa se preocupar com qualquer aspecto de servidores, máquinas virtuais ou contêineres é incrivelmente atraente.
Uma função Lambda é um serviço sem estado. Normalmente, ele lida com solicitações invocando serviços da AWS. Por exemplo, uma função Lambda que é invocada quando uma imagem é carregada em um bucket S3 pode inserir um item em uma tabela de imagens do DynamoDB e publicar uma mensagem em um fluxo do Kinesis para acionar o processamento de imagem. Uma função Lambda também pode invocar serviços web de terceiros.
Há quatro maneiras de invocar uma função Lambda:
cronograma
Como você pode ver, o AWS Lambda é uma maneira conveniente de implantar microsserviços. O preço baseado em solicitação significa que você paga apenas pelo trabalho que seus serviços realmente realizam. Além disso, como você não é responsável pela infraestrutura de TI, pode se concentrar no desenvolvimento do seu aplicativo.
Existem, no entanto, algumas limitações significativas. Ele não se destina a ser usado para implantar serviços de longa duração, como um serviço que consome mensagens de um corretor de mensagens de terceiros. As solicitações devem ser concluídas em 300 segundos. Os serviços devem ser sem estado, pois, em teoria, o AWS Lambda pode executar uma instância separada para cada solicitação. Eles devem ser escritos em um dos idiomas suportados. Os serviços também devem começar rapidamente; caso contrário, eles podem expirar e ser encerrados.
Implantar um aplicativo de microsserviços é desafiador. Existem dezenas ou até centenas de serviços escritos em diversas linguagens e estruturas. Cada um é um miniaplicativo com seus próprios requisitos específicos de implantação, recursos, dimensionamento e monitoramento. Existem vários padrões de implantação de microsserviços, incluindo Instância de Serviço por Máquina Virtual e Instância de Serviço por Contêiner. Outra opção intrigante para implantar microsserviços é o AWS Lambda, uma abordagem sem servidor. Na próxima e última parte desta série, veremos como migrar um aplicativo monolítico para uma arquitetura de microsserviços.
Editor – Esta série de artigos em sete partes está agora completa:
Você também pode baixar o conjunto completo de artigos, além de informações sobre a implementação de microsserviços usando o NGINX Plus, como um e-book – Microsserviços: Do design à implantação . E veja nossa série sobre a Arquitetura de Referência de Microsserviços e a página Soluções de Microsserviços .
O blogueiro convidado Chris Richardson é o fundador do CloudFoundry.com original, um dos primeiros Java PaaS (Plataforma como Serviço) para Amazon EC2. Agora, ele presta consultoria a organizações para melhorar a maneira como elas desenvolvem e implantam aplicativos. Ele também escreve regularmente sobre microsserviços em https://microservices.io .
"Esta postagem do blog pode fazer referência a produtos que não estão mais disponíveis e/ou não têm mais suporte. Para obter as informações mais atualizadas sobre os produtos e soluções F5 NGINX disponíveis, explore nossa família de produtos NGINX . O NGINX agora faz parte do F5. Todos os links anteriores do NGINX.com redirecionarão para conteúdo semelhante do NGINX no F5.com."