Serverless e FaaS
LidoEsta aula explora o paradigma serverless e Function as a Service (FaaS), explicando o que são, quando utilizá-los, seus trade-offs e o problema dos cold starts. Inclui exemplos práticos, boas práticas e exercícios para fixação.
Serverless e FaaS representam uma evolução significativa na forma como desenvolvemos e implantamos software. Em vez de gerenciar servidores, o desenvolvedor foca exclusivamente no código de funções individuais, que são executadas em resposta a eventos. Este modelo oferece escalabilidade automática, cobrança por uso e redução de overhead operacional, mas também introduz novos desafios como latência de inicialização e complexidade de monitoramento.
Nesta aula, vamos mergulhar nos conceitos fundamentais de Functions as a Service, entender quando essa arquitetura faz sentido, analisar os prós e contras, e discutir um dos principais vilões do serverless: os cold starts. Ao final, você terá uma visão clara para decidir se serverless é a escolha certa para seus projetos.
Functions as a Service
FaaS é um serviço de computação em nuvem que permite executar código em resposta a eventos, sem a necessidade de provisionar ou gerenciar servidores. O código é organizado em funções, que são implantadas de forma independente e executadas em contêineres efêmeros gerenciados pelo provedor. Cada função é acionada por um gatilho, como uma requisição HTTP, uma mensagem em uma fila, uma alteração em um banco de dados ou um upload de arquivo.
Os principais provedores de FaaS incluem AWS Lambda, Google Cloud Functions, Azure Functions e Cloudflare Workers. Cada um oferece um runtime para várias linguagens (Node.js, Python, Go, etc.), integração com outros serviços da nuvem e um modelo de precificação baseado em execução (número de invocações) e duração (tempo de execução).
Um exemplo simples de função em AWS Lambda (usando Python) seria:
import json
def lambda_handler(event, context):
# event contém os dados de entrada
name = event.get('name', 'Mundo')
return {
'statusCode': 200,
'body': json.dumps(f'Olá, {name}!')
}
Nesse exemplo, a função recebe um evento (que pode ser um objeto JSON de uma requisição API Gateway) e retorna uma resposta. O provedor cuida de tudo: infraestrutura, escalabilidade, patches de segurança, etc.
No contexto de DevOps, o FaaS se destaca por permitir implantações rápidas e frequentes. Você pode atualizar uma função independentemente das outras, sem derrubar o sistema. Ferramentas como Serverless Framework e AWS SAM facilitam o gerenciamento do ciclo de vida das funções, integrando-se a pipelines de CI/CD.
Quando usar
FaaS é ideal para cargas de trabalho intermitentes ou com picos imprevisíveis. Se você tem um serviço que fica ocioso a maior parte do tempo, como um webhook, um processador de eventos ou uma API de baixo tráfego, serverless pode reduzir drasticamente os custos, pois você paga apenas pelo que executa.
Outros casos de uso comuns incluem:
- Processamento de arquivos (imagens, vídeos) quando são enviados para um bucket de armazenamento.
- ETL (Extract, Transform, Load) de dados em pipelines de dados.
- Backends para aplicações móveis ou web, especialmente quando o tráfego é variável.
- Automação de tarefas de infraestrutura (por exemplo, ajustar recursos de acordo com eventos).
- Chatbots e integrações com serviços de mensageria.
Além disso, FaaS é uma excelente escolha para equipes que desejam reduzir a complexidade operacional e acelerar o desenvolvimento. Como não há servidores para gerenciar, o time pode se concentrar em escrever código de negócio, enquanto o provedor cuida da infraestrutura.
No entanto, é importante avaliar se a aplicação se encaixa no modelo. Se você tem um serviço com tráfego constante e previsível, um contêiner ou uma máquina virtual pode ser mais econômico e oferecer melhor desempenho.
Trade-offs
Embora o serverless traga muitos benefícios, também há desvantagens que devem ser consideradas:
- Limitações de execução: Funções têm tempo máximo de execução (por exemplo, 15 minutos no AWS Lambda). Processos de longa duração não são adequados.
- Cold starts: A primeira invocação após um período de inatividade pode ter latência adicional (discutido a seguir).
- Dificuldade de depuração: A observabilidade é mais complexa, pois as funções são efêmeras e distribuídas. É necessário usar ferramentas como X-Ray, CloudWatch ou similar.
- Vendor lock-in: Cada provedor tem APIs e serviços específicos. Migrar entre provedores pode ser trabalhoso.
- Custo em escala: Para cargas muito altas e contínuas, o custo pode ser maior do que com servidores dedicados.
- Complexidade de arquitetura: Aplicações serverless tendem a ser mais fragmentadas, exigindo mais integrações e gerenciamento de eventos.
Outro ponto é o gerenciamento de estado. Funções são stateless por padrão; se você precisa manter estado entre invocações, deve usar serviços externos como DynamoDB ou Redis.
Por fim, a segurança também é uma consideração. Como o ambiente é compartilhado, é crucial configurar permissões corretamente e garantir que as funções não exponham dados sensíveis.
Cold starts
Cold start é o tempo adicional necessário para inicializar uma função antes de executar o código, quando ela não foi invocada recentemente. Isso ocorre porque o provedor precisa provisionar um novo contêiner, configurar o runtime e carregar o código. Esse atraso pode variar de alguns milissegundos a vários segundos, dependendo da linguagem, do tamanho da função e do provedor.
O cold start é um dos principais desafios do FaaS, especialmente para aplicações sensíveis à latência, como APIs de tempo real. No AWS Lambda, por exemplo, o tempo de cold start para Node.js é geralmente menor que para Java ou .NET, devido ao tempo de inicialização da JVM.
Estratégias para mitigar cold starts incluem:
- Manter funções aquecidas: Usar um agendador (por exemplo, CloudWatch Events) para invocar a função periodicamente, evitando que ela seja destruída.
- Reduzir o tamanho do pacote: Menos dependências e código menor aceleram a inicialização.
- Escolher linguagens com inicialização rápida: Python e Node.js são mais rápidos que Java e C#.
- Usar provisioned concurrency: Serviços como Lambda Provisioned Concurrency mantêm um número definido de contêineres quentes, eliminando cold starts (mas com custo adicional).
- Otimizar o runtime: Em alguns casos, custom runtimes podem ser otimizados.
Vamos ver um exemplo de como simular um cold start em um teste local (em bash, apenas para demonstrar o conceito):
#!/bin/bash
# Simula uma função que demora a inicializar
echo "Inicializando função..."
sleep 2 # Simula o tempo de cold start
echo "Função executada!"
Em produção, o cold start é invisível para o provedor, mas perceptível para o usuário final. Portanto, é essencial medir e monitorar a latência para decidir se o serverless é adequado para o seu caso.
Boas práticas
- Projete funções pequenas e focadas em uma única responsabilidade.
- Utilize variáveis de ambiente para configuração, evitando código hardcoded.
- Implemente logs estruturados e métricas para facilitar a observabilidade.
- Gerencie dependências com cuidado, evitando bibliotecas pesadas.
- Configure alertas para falhas e tempo de execução.
- Use infraestrutura como código (IaC) para gerenciar funções e recursos relacionados.
- Teste localmente com ferramentas como SAM CLI ou Serverless Framework.
Referências
- AWS Lambda
- Google Cloud Functions
- Azure Functions
- Serverless Framework
- AWS Lambda Documentation
- Serverless Architectures - Martin Fowler
- Function as a Service - Wikipedia
- Cloudflare Workers
Exercícios
- Explique o que é FaaS e como ele difere de uma arquitetura de servidores tradicionais.
- Cite três cenários em que o uso de FaaS é vantajoso e explique o porquê.
- Quais são os principais trade-offs do serverless? Liste pelo menos três.
- O que é cold start e como ele afeta a experiência do usuário? Descreva duas estratégias para mitigá-lo.
- Escreva um exemplo de função FaaS em Python (ou outra linguagem) que receba um evento e retorne uma mensagem personalizada.
def handler(event, context):
name = event.get('name', 'Mundo')
return f'Olá, {name}!'