Funções Serverless em Rust: AWS Lambda de A a Z

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Introdução: Por que Rust para Serverless é um avanço

\n\n

A arquitetura Serverless já se tornou padrão para construir aplicações escaláveis e econômicas. No entanto, a escolha tradicional de linguagens (Python, Node.js, Java) frequentemente enfrenta o problema do cold start e alto consumo de memória. Rust, com seu custo zero de abstrações e ausência de garbage collector, oferece uma solução revolucionária. Neste artigo, vamos abordar como criar, configurar e fazer deploy de funções serverless em Rust para AWS Lambda — desde a instalação das ferramentas até lançamentos em produção.

\n\n

Ao final do artigo, você será capaz de:

\n
    \n
  • Configurar o ambiente para desenvolvimento Rust + AWS Lambda
  • \n
  • Escrever uma função eficiente com tratamento de eventos
  • \n
  • Otimizar o binário para tempo mínimo de cold start
  • \n
  • Implantar a função na AWS usando Cargo Lambda
  • \n
\n\n

Preparação do ambiente: Cargo Lambda e AWS CLI

\n\n

Para trabalhar com Rust no AWS Lambda, precisamos de uma ferramenta especial — cargo-lambda. Ela automatiza a compilação, teste e deploy. Vamos instalá-la via Cargo:

\n\n
cargo install cargo-lambda
\n\n

Certifique-se também de ter aws-cli (configurado com chaves IAM) e Docker (para testes locais) instalados. Vamos criar um novo projeto:

\n\n
cargo lambda new my-rust-lambda\ncd my-rust-lambda
\n\n

O comando criará uma estrutura básica com os arquivos Cargo.toml e src/main.rs. Observe as dependências no Cargo.toml:

\n\n
[package]\nname = "my-rust-lambda"\nversion = "0.1.0"\nedition = "2021"\n\n[dependencies]\nlambda_runtime = "0.11"\ntokio = { version = "1", features = ["macros", "rt-multi-thread"] }\nserde = { version = "1.0", features = ["derive"] }\nserde_json = "1.0"\ntracing = { version = "0.1", features = ["log"] }\ntracing-subscriber = { version = "0.3", features = ["fmt"] }
\n\n

A biblioteca chave é lambda_runtime. Ela fornece o trait LambdaHandler, que iremos implementar.

\n\n

Escrevendo a primeira função: processamento de requisição API Gateway

\n\n

Vamos considerar o cenário clássico: uma função que recebe um JSON com o nome do usuário e retorna uma saudação. Abra src/main.rs e escreva o seguinte código:

\n\n
use lambda_runtime::{run, service_fn, Error, LambdaEvent};\nuse serde::{Deserialize, Serialize};\n\n#[derive(Deserialize)]\nstruct Request {\n    name: String,\n}\n\n#[derive(Serialize)]\nstruct Response {\n    message: String,\n}\n\nasync fn function_handler(event: LambdaEvent<Request>) -> Result<Response, Error> {\n    let name = event.payload.name;\n    let message = format!("Olá, {}! Você acabou de executar Rust no Lambda!", name);\n    Ok(Response { message })\n}\n\n#[tokio::main]\nasync fn main() -> Result<(), Error> {\n    tracing_subscriber::fmt()\n        .with_max_level(tracing::Level::INFO)\n        .init();\n\n    run(service_fn(function_handler)).await\n}
\n\n

Vamos analisar os pontos-chave:

\n
    \n
  • LambdaEvent<Request> — estrutura que contém o corpo da requisição e o contexto de execução.
  • \n
  • #[tokio::main] — runtime assíncrono necessário para o funcionamento do Lambda runtime.
  • \n
  • serde — desserialização do JSON de entrada e serialização da resposta.
  • \n
\n\n

Teste localmente:

\n\n
cargo lambda watch
\n\n

Em seguida, em outro terminal:

\n\n
cargo lambda invoke --data-ascii '{"name": "Alexandre"}'
\n\n

Você deve ver: {"message":"Olá, Alexandre! Você acabou de executar Rust no Lambda!"}

\n\n

Otimização do cold start e tamanho do binário

\n\n

A principal vantagem do Rust é o cold start mínimo. No entanto, para alcançá-lo, é necessário compilar o bi

Blogs

Book Recommendations