Funciones serverless en Rust en AWS Lambda: guía completa

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Introducción: Por qué Rust es el lenguaje ideal para Serverless



La arquitectura serverless se ha convertido en el estándar para las aplicaciones modernas en la nube. Sin embargo, los lenguajes clásicos (Python, Node.js) a menudo sufren de un arranque en frío lento y un alto consumo de memoria. Rust resuelve estos problemas: sus binarios compilados se inician en milisegundos y el consumo de memoria es mínimo. En este artículo, analizaremos cómo crear, desplegar y optimizar funciones de AWS Lambda en Rust, desde la configuración del entorno hasta el despliegue en producción.



1. Configuración del entorno y herramientas



Instalación de Rust y Cargo Lambda

Para trabajar con AWS Lambda en Rust necesitarás:

  • Rust (instalación a través de rustup)
  • Cargo Lambda — la herramienta oficial para compilación y despliegue
  • AWS CLI con credenciales configuradas


# Instalación de Rustcurl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

# Instalación de Cargo Lambdacargo install cargo-lambda

# Verificacióncargo lambda --version


Creación de un nuevo proyecto

Cargo Lambda genera automáticamente una plantilla con soporte para Lambda Runtime API:



cargo lambda new my-rust-lambdacd my-rust-lambda


La estructura del proyecto incluye Cargo.toml con las dependencias lambda_runtime y serde, así como un archivo src/main.rs con una función controladora básica.



2. Escritura de la primera función Serverless en Rust



Estructura básica del controlador

Veamos una función Lambda simple que recibe un JSON con un nombre y devuelve un saludo:



use lambda_runtime::{service_fn, LambdaEvent, Error};use serde::{Deserialize, Serialize};

#[derive(Deserialize)]struct Request { name: String,}

#[derive(Serialize)]struct Response { message: String, request_id: String,}

async fn handler(event: LambdaEvent<Request>) -> Result<Response, Error> { let req = event.payload; let resp = Response { message: format!("¡Hola, {}! ¡Estás en Rust!", req.name), request_id: event.context.request_id, }; Ok(resp)}

#[tokio::main]async fn main() -> Result<(), Error> { lambda_runtime::run(service_fn(handler)).await}


Puntos clave:

  • service_fn envuelve la función asíncrona en un controlador
  • LambdaEvent contiene el payload y el contexto (request_id, deadline, etc.)
  • Serialización/deserialización a través de serde


Pruebas locales

Antes del despliegue, probemos la función localmente:



cargo lambda watch# En otra terminal:cargo lambda invoke --data-ascii '{"name": "Mundo"}'


Deberías obtener la respuesta: {"message":"¡Hola, Mundo! ¡Estás en Rust!","request_id":"..."}



3. Trabajo con servicios de AWS (S3, DynamoDB)



Integración con S3 a través de AWS SDK

Agreguemos a Cargo.toml:



[dependencies]aws-sdk-s3 = "1.0"aws-config = "1.0"


Ejemplo de una función que lee un objeto de S3:



use aws_sdk_s3::Client;

async fn handler(event: LambdaEvent<Request>) -> Result<Response, Error> { let config = aws_config::load_from_env().await; let s3_client = Client::new(&config);

let bucket = "my-bucket"; let key = &event.payload.name;

let object = s3_client .get_object() .bucket(bucket) .key(key) .send() .await?;

let body = object.body.collect().await?; let content = String::from_utf8(body.to_vec())?;

Ok(Response { message: format!("Contenido del archivo: {}", content), request_id: event.context.request_id, })}


En

Blogs

Book Recommendations