Muito se fala sobre a capacidade que a nuvem pública tem de reduzir custos com infraestrutura de aplicações. E é verdade, este é, de fato, um dos principais aspectos responsáveis por fazer com que as plataformas de nuvem se tornassem super populares e aceitas no mercado. Além do custo, existe outro aspecto trazido pela nuvem que é extremamente desejável para empresas que criam soluções em software – a possibilidade de terceirizar inteiramente o ambiente de execução para a plataforma de nuvem. Mas, será que o fato puro e simples de levar uma aplicação para a nuvem é suficiente para se conseguir uma redução considerável de custos? Além disso, será que é possível a qualquer aplicação terceirizar inteiramente o processamento para o provedor de nuvem?
Ambos os aspectos mencionados no parágrafo anterior (redução de custos + terceirização do ambiente) estão diretamente associados com um conceito fundamental de arquitetura de aplicações de nuvem: serverless computing. Dessa forma, no artigo de hoje, iremos explorar juntos (e de maneira um pouco mais demorada) este tema. Entenderemos “porque” é tão importante para uma aplicação utilizar sempre que possível, este modelo arquitetural e ainda, identificaremos maneiras de fazer isso na plataforma de nuvem da Microsoft – o Azure.
O que é “Serverless Computing”?
Serverless computing (em português algo próximo a “computação sem servidores”) refere-se a capacidade que determinada plataforma de nuvem possui de executar códigos sob demanda sem a alocação full time de servidores estáticos para este fim e com modelo de cobrança baseado, geralmente, apenas em consumo. Associado a este termo, está portanto o de “Serverless Architectures”, que define arquiteturas de aplicações para serem executadas sobre o modelo de serverless computing.
Para que esta ideia fique mais clara, vamos trabalhar com um exemplo fictício (mas que está bem próximo de algo real). Nosso exemplo refere-se a uma aplicação web convencional criada para gerenciar a venda de livros e ebooks (ou qualquer outro produto que você queira, isso não é o que importa aqui). Trata-se de uma aplicação convencional com frontend 100% em HTML (com algum framework JS) e backend escrito em .NET residente em um projeto do tipo Web API. O sistema utiliza banco de dados NoSQL para a aplicação e dispara emails para os usuários com notificações sobre as compras. A Figura 1 apresenta a arquitetura atual (monolítica) da aplicação.
Figura 1. Arquitetura da aplicação fictícia de vendas
Como é possível visualizar, trata-se de uma aplicação com arquitetura monolítica onde, um frontend Javascript faz requisições a um backend .NET. Realidade bem próxima de muitas aplicações da vida real, certo? Existem elementos adicionais dessa arquitetura: um fila (que serve aqui como um repositório temporário de mensagens que deverão ser encaminhadas por email para os usuários que efetuam compras no portal), um web-hook do serviço terceiro de pagamentos que envia notificações sobre novas compras, um serviço externo que, todos os dias a noite, faz um consolidado das vendas do dia e gera um relatório e finalmente, um microserviço que existe apenas para realizar a validação de uma licença gerada e que será atribuída ao usuário que está comprando algo. Não adicionei o banco de dados NoSQL no desenho, mas, tenha a certeza de que ele está ali servindo os serviços de backend.
Se pensarmos em termos de recursos de nuvem (vamos utilizar o Azure para montar este ambiente), baseado em cenários mais comumente encontrados no dia-a-dia, para executar esta aplicação, poderíamos ter pelo menos:
- API principal e frontend: 1 máquina virtual D2 v2 com Windows Server.
- Fila: 1 máquina virtual com Linux Basic A2 rodando algum serviço de fila ou cache (Redis, Kafka, ou outro).
- API de validação de licença: 1 máquina virtual Linux Basic A1 com Docker rodando containers.
- Geração de relatórios: 1 App Service Basic B1 para rodar um Web Job agendado.
- Banco de dados: 1 Storage Accout para ter acesso ao Azure Tables.
A arquitetura Serverless tomaria este modelo monolítico apresentado pela Figura 1 e terceirizaria o máximo possível de rotinas para que pudessem ser executadas apenas sob demanda, de maneira transacional. O custo aplicado seria sobre o número total de execuções daqueles ambientes. No caso da aplicação acima poderíamos ter as seguintes rotinas terceirizadas (veja a Figura 2):
Figura 2. Desacoplando rotinas da aplicação de vendas em serverless services
Esta quebra simples de algumas rotinas do backend já seria suficiente para remover alguns elementos do ambiente. Por exemplo, ao invés de termos uma máquina para rodar o serviço de filas, poderíamos simplesmente recorrer a um Azure Queues. Outro aspecto que seria otimizado é a remoção da máquina existente para rodar um container de validação de licenças. Agora o serviço serverless fará isso para você. Além disso, ao tirarmos responsabilidades da API e terceirizarmos para serviços serverless (porque na prática é isso que estamos fazendo), distribuímos a carga do sistema de maneira escalável e altamente disponível. Isso faria com que, por exemplo, não precisássemos de uma máquina virtual tão robusta para executar as chamadas da API.
Uma observação importante aqui é: nem todas as rotinas de uma aplicação podem, imediatamente, serem convertidas para serverless. Associado a este conceito de serverless architectures está também o de stateless architectures. Dado o caráter completamente transacional e volátil (onde não há qualquer tipo de conservação de estado) dos serviços serverless, é fundamental que a aplicação não conserve em si informações de persistência relevantes para que outras rotinas possam ser completadas. Por exemplo: dados de login, códigos de compra, etc. Deve existir antes da “quebra” em serverless, uma análise criteriosa da aplicação e, se preciso, novos elementos precisarão ser adicionados à infra. Em geral, caches e filas são adicionados neste contexto.
Por que serverless ao invés de outras abordagens?
O que você pode estar pensando a esta altura é: ok, entendi o que é serverless computing/architecture e já percebi que é bem bacana, entretanto, por que eu usaria serviços serverless ao invés de Web Apps, por exemplo? Ou até mesmo máquinas virtuais, onde eu posso colocar diferentes serviços para serem executados no mesmo ambiente?
Vamos pensar primeiro no aspecto “custo”. O custo mensal aproximado daquele (antes da quebra em serviços menores) ambiente (utilizando a calculadora do Azure, disponível aqui), da forma como está, será algo em torno de US$ 350,00 (aproximadamente R$ 1.300,00). É claro que, este custo por si só, já é mais baixo que manter esta mesma aplicação em ambiente local, entretanto, precisamos concordar que o custo deste ambiente pode ser bem mais baixo. Eis o primeiro aspecto pelo qual você precisa considerar serviços serverless. Poucas estratégias são tão eficientes para se reduzir custos de infraestrutura na nuvem como a adição de serviços serverless nas arquiteturas das aplicações.
Se fossemos fazer uma comparação superficial de custos entre os dois ambientes (aquele sem a quebra em serviços menores da Figura 1 com aquele segmentado em rotinas serverless da Figura 2), teríamos os seguintes valores aproximados:
- Ambiente antes da quebra em serverless: R$ 1.300,00
- Ambiente depois da quebra de 5 rotinas: R$ 780,00
É claro que estes são valores aproximados. Não temos nenhuma volumetria real em mãos para que possamos dimensionar de maneira mais exata o sizing da aplicação. De toda maneira, com os valores padrão das Functions (400.000 GB de tráfego + 1.000.000 de execuções grátis), chegamos a uma economia aproximada de 60% entre os ambientes. Isso porque esta “quebra” do ambiente em serviços serverless possibilitou a remoção de duas máquinas virtuais e ainda, reduziu a responsabilidade da API do backend, fazendo com que pudéssemos diminuir a dimensão da mesma.
Além do aspecto relacionado ao custo, analisando esta arquitetura da Figura 1 com critérios técnicos, é possível identificar uma série de GAPs, certo? Vamos aos principais:
- Pontos únicos de falha. Veja as VMs mencionadas, por exemplo. Não existe redundância entre elas (1 VM unitária para rodar cada tipo de workload). O que ocorreria se, por alguma razão, as vendas aumentassem consideravelmente e os servidores ficassem, por exemplo, com memória insuficiente para atender a todas as requisições? Ou ainda, imagine que, por alguma razão, o disco da VM se degrade e ela saia do ar. Problemas, certo?
- Escala. Só há uma maneira de fazer com que esta estrutura escale com um eventual crescimento de demanda: escalar manualmente através da adição de novas máquinas abaixo de um load balancer.
- DevOps pipeline. Muito embora seja perfeitamente possível configurar pipelines de entrega contínua para máquinas virtuais com alguma ferramenta especializada, precisamos concordar que trata-se de um processo consideravelmente mais custoso (operacionalmente falando). Além disso, precisamos pensar em como ficariam os ambientes de Dev/Homolog neste cenário, uma vez que estamos falando de uma ambiente principal de produção apenas.
- Alto custo operacional. O custo a que me refiro aqui não é financeiro, (muito embora impacte também) mas sim, operacional. Manter todos os ambientes atualizados e configurados de forma manual é, frequentemente, indesejável para qualquer modelo de aplicação. Isso porque eleva em escala considerável a sucessão a falhas.
- Segurança. Este é outro ponto de atenção aqui. Como funcionaria a estratégia de certificados, por exemplo, nesse modelo? A renovação destes certificados? Seriam feitas manualmente?
Ao optar por recursos serverless na sua arquitetura, você também “ganhará” em relação aos aspectos mencionados acima. Isso porque, de maneira geral, estes recursos são de plataforma e como todos os serviços dessa natureza, implementam de maneira nativa escalabilidade automática, alta disponibilidade, processo simplificado de DevOps e baixíssimo custo operacional, uma vez que se tratam apenas de “containers” de execução voláteis. Você, de maneira geral, precisa apenas entregar seu código funcional lá, configurar eventuais agendamentos e pronto, a plataforma fará o restante pra você.
Como o Azure está entregando serverless computing?
Existem basicamente três tipos de serviços disponíveis no Azure que entregam serverless computing. Vou apresentar os três e provendo informações básicas sobre cada um deles (falar sobre os serviços não é o objetivo deste texto).
Azure Automation
Serviço serverless que oferece a possibilidade de realizar automações no ambiente. A ideia aqui é que o usuário tenha o poder para realizar, de maneira agendada e em background, operações comuns em suas infraestruturas. Exemplos clássicos que temos implementado em clientes: ligar e desligar de máquinas virtuais em horários específicos (ambientes de Dev/Homolog, por exemplo, que precisam estar disponíveis apenas durante as horas úteis de trabalho), scripts automatizados para modificar tamanhos de máquinas virtuais, dentre outros. Azure Automator suporta scripts diretamente ou a construção de fluxos de execução de scripts, sempre com PowerShell. A Figura 3 apresenta o trecho de um runbook do Azure Automator que liga/desliga uma máquina virtual. Note que o foco deste serviço é a automatização de recursos de infraestrutura.
Figura 3. Trecho de código PowerShell que liga/desliga máquinas virtuais
Azure Web Jobs
Serviço serverless que possibilita a execução de trechos de códigos sob demanda, de maneira agendada ou ainda, de maneira contínua em background, disponibilizado abaixo do guarda-chuvas de App Services. Diferentemente dos scripts de automação mencionado anteriormente, aqui você pode executar scripts PowerShell, bash ou trechos de código em qualquer outra linguagem suportada (C#, Node, PHP, Python, etc). Web Jobs rodam sobre os planos de hospedagem dos Apps Services. Essa é uma informação importante porque quer dizer que, se um Web Job for criado sob o mesmo plano de hospedagem de sua aplicação web, ele estará concorrendo pelos mesmos recursos “físicos” da aplicação. Dependendo da criticidade da aplicação web, do Web Job e das configurações do plano de hospedagem, problemas de performance (ou até mesmo de disponibilidade) poderão ocorrer. Além disso, o modelo de cobrança é constante, independente de os Web Jobs serem consumidos ou não sob demanda. Isso quer dizer que a quantidade de chamadas ou tempo de execução dos Web Jobs não impactarão no valor final de pagamento, isso porque a cobrança já está definida no plano de hospedagem.
Com estas informações fica claro, portanto, que o foco dos Web Jobs está na execução de quaisquer tarefas de background com custo pré-definido. A Figura 4 apresenta alguns Web Jobs criados em três diferentes modelos.
Figura 4. Web Jobs criados para rodar continuamente, agendada ou sob demanda
Azure Functions
Azure Functions é a resposta da Microsoft em relação a construção de um modelo serverless ainda mais flexível (especialmente em relação ao modelo de cobrança) do que os Web Jobs. Na verdade, o recurso de Functions foi construído sobre os Web Jobs. Você pode sim enxergar os Functions como uma evolução dos Web Jobs, uma vez que possui um modelo de cobrança mais flexível (por chamada/demanda ou por plano de hospedagem) e possui uma quantidade consideravelmente maior de integrações nativas com outros serviços e ferramentas da Microsoft, não apenas no Azure (Logic Apps, Web Apps, Service Bus, Azure Tables, etc) mas também com as ferramentas de desenvolvimento (Visual Studio, Visual Studio Code, SQL Management Tool, etc). Outro aspecto super importante em relação aos Functions é a suave integração com ferramentas de DevOps. Entregar o código de suas functions de maneira contínua é bem simples.
A Figura 5 apresenta uma Function criada através do portal do Azure.
Figura 5. Function criada a partir do portal do Azure
Concluindo
Recentemente, em um evento nos Estados Unidos, o CVP da divisão de cloud da Microsoft, Scott Guthrie disse:
“I certainly think the model of a very consumption driven pricing … is the direction that everything is going. This has taken consumption to the next logical extreme, where there is no overhead”
E cá entre nós, faz todo o sentido essa afirmação. É evidente que ainda levará um tempo para que as aplicações se ajustem para o modelo serverless entretanto, diante das inegáveis vantagens, fica difícil negar que em breve o modelo entregue por serverless computing será um dos mais adotados. Novas aplicações, já nascidas para a nuvem, idealmente, deveriam ter suas arquiteturas voltadas para serverless. Os benefícios são técnicos e também, nos negócios.
Aplicações que já existem também podem usufruir dos benefícios do modelo serverless, conforme vimos no exemplo deste texto, entretanto, uma análise criteriosa da aplicação precisa ser realizada no sentido de identificar pontos de impacto gerados pela terceirização da execução.
Por hoje é isso. Até a próxima!
Pingback: Terceirizando o envio de emails do Arda com Azure Functions – Fabrício Sanchez