Fundamentos da computação em nuvem
Computação Serverless
O que 'serverless' realmente significa, como uma função escala do zero a milhares de requisições e volta, a matemática real por trás do custo, e onde ficam os limites dela.
- Explicar o que é computação serverless e corrigir o mal-entendido de que nenhum servidor está envolvido
- Descrever o ciclo de vida orientado a eventos de uma função serverless, incluindo cold starts e warm starts
- Calcular se uma carga de trabalho custa menos como função serverless ou como servidor sempre ligado, usando o volume de requisições e a duração
- Identificar os limites de tempo de execução e de estado que tiram uma função serverless de cena para uma carga de trabalho
- Comparar funções serverless com contêineres e máquinas virtuais no espectro de controle versus conveniência
O espectro não mostrou esta parte
Na lição de computação, você viu funções serverless na ponta direita do espectro de controle versus conveniência: a plataforma gerencia tudo, exceto o seu código, e uma função inicia em milissegundos. Aquele diagrama cumpre bem o papel de mostrar onde o serverless fica em relação a máquinas virtuais e contêineres, mas não mostra o que "a plataforma gerencia tudo" significa na prática, nem onde ficam os limites dessa conveniência. As duas coisas importam na hora de decidir se uma carga de trabalho cabe em uma função serverless.
Sem servidor é o nome de marketing, não o mecanismo
"Serverless" é o nome que o mercado deu a esse modelo, não uma descrição literal. A AWS roda sua função dentro de uma micro máquina virtual isolada, em uma frota própria de servidores físicos, usando uma tecnologia de virtualização chamada Firecracker sobre o Nitro System da AWS. Azure e Google Cloud fazem o equivalente no hardware deles. O que "serverless" tira de você não é o servidor, é o trabalho de escolher, dimensionar, corrigir e escalar esse servidor. Compare isso com IaaS, onde você escolhe o tipo de instância, ou até PaaS, onde pelo menos você escolhe um runtime e uma política de escalonamento. Uma função serverless não entrega nenhum dos dois: você entrega uma função, conecta um gatilho, e o provedor decide quantas cópias dela rodar, onde, e por quanto tempo cada uma vive.
O ciclo orientado a eventos: ocioso, invocação, execução, ocioso de novo
Uma função serverless não fica ligada esperando trabalho como uma máquina virtual fica. Imagine uma função que gera uma miniatura toda vez que um cliente sobe uma foto para um bucket de armazenamento. Na maior parte do dia, zero cópias dessa função estão rodando em qualquer lugar, e isso não custa nada. No momento em que uma foto chega no bucket, o evento dispara uma invocação: a plataforma encontra ou cria um ambiente de execução, roda o seu código handler contra o evento, e devolve um resultado. Quando o fluxo de uploads para por um tempo, a plataforma libera esse ambiente, e a função volta a zero.
Cold start e warm start
Essa distinção entre "encontra ou cria" tem nome. Se um ambiente de execução de uma invocação recente ainda está disponível, a plataforma o reaproveita, um warm start, que roda seu handler quase na hora. Se não, depois de um período ocioso ou de uma explosão de tráfego novo, a plataforma primeiro precisa inicializar um ambiente novo, carregar o runtime e importar as dependências antes mesmo de rodar o handler, um cold start. Esse trabalho de inicialização não é de graça, nem em tempo nem em dinheiro: a cobrança atual do AWS Lambda conta a fase de inicialização de um cold start como duração cobrada, igual ao handler em si. Uma função chamada o tempo todo raramente paga esse imposto do cold start, porque os ambientes ficam quentes; uma função chamada em rajadas ocasionais paga esse imposto na primeira requisição de cada rajada.
A matemática por trás de "pague só pelo que roda"
O preço on-demand do AWS Lambda cobra US$ 0,20 por milhão de requisições, mais US$ 0,0000166667 por GB-segundo de tempo de execução, com um nível gratuito de 1 milhão de requisições e 400.000 GB-segundos todo mês, para sempre.
Pegue uma função configurada com 512 MB de memória (0,5 GB) que roda por 400 milissegundos (0,4 segundos), chamada 100.000 vezes por mês, geração de miniaturas para um app pequeno de compartilhamento de fotos, por exemplo. Essa carga usa 100.000 x 0,5 x 0,4 = 20.000 GB-segundos e 100.000 requisições, os dois confortavelmente dentro do nível gratuito. A fatura: US$ 0.
Agora escale a mesma função para 5 milhões de invocações por mês, um app mais movimentado, ou o mesmo app que cresceu. São 5.000.000 x 0,5 x 0,4 = 1.000.000 GB-segundos, dos quais 600.000 são cobráveis depois do nível gratuito, mais 4.000.000 requisições cobráveis. A duração custa cerca de 600.000 x US$ 0,0000166667, uns US$ 10,00, e as requisições somam mais 4 x US$ 0,20 = US$ 0,80, para uma fatura de uns US$ 10,80 por mês. Compare isso com a t3.micro da lição de computação, cerca de US$ 7,59 por mês rodando o tempo todo, faça ela trabalho ou não. Em volume baixo e picado, o serverless ganha de longe, é de graça. Em volume alto e constante, uma instância sempre ligada consegue custar menos, e isso antes de perguntar se uma única t3.micro aguentaria 5 milhões de requisições sem cair.
Onde uma função serverless para de servir
Dois limites pesam tanto quanto a matemática do custo. Primeiro, tempo de execução: funções do AWS Lambda travam em um teto de 15 minutos por invocação; um job de codificação de vídeo que roda por 2 horas simplesmente não cabe em uma função serverless comum, não importa quão favorável seja a conta por requisição. Segundo, estado: um ambiente de execução pode ser reaproveitado entre invocações, mas nada garante isso, então uma função não pode contar com dados ficando na memória ou uma conexão ficando aberta de uma invocação para a próxima. Uma carga que precisa de um pool de conexões de banco de dados de longa duração, um job em lote de várias horas, ou estado garantido em memória pertence a um contêiner ou a uma máquina virtual, não a uma função serverless.
Pistas de exame: identificando o encaixe em um cenário
| O cenário diz... | Aponta para |
|---|---|
| "Roda só quando é acionado", "orientado a eventos", "sem servidores para gerenciar" | Função serverless |
| "Tráfego imprevisível", "ocioso na maior parte do dia" | Função serverless |
| "Precisa de conexão persistente", "roda continuamente por horas" | Contêiner ou máquina virtual |
| "Volume alto e constante o dia inteiro" | Contêiner ou máquina virtual (o cruzamento de custo favorece o sempre ligado) |
Onde isso deixa você
Serverless não tira o servidor de cena, tira o seu trabalho de administrá-lo, e cobra só pelos milissegundos que o seu código realmente roda. Essa troca compensa em volume baixo ou picado, e pode perder para uma instância sempre ligada em volume alto e constante, e é exatamente por isso que "serverless é sempre mais barato" é uma armadilha, não uma regra. A próxima lição deixa para trás a pergunta de quem administra o servidor e faz uma diferente: como a própria aplicação deveria ser dividida em partes, e como essas partes rodam do mesmo jeito em todo ambiente. É isso que contêineres e microsserviços respondem.
