DEfinir el controlador de funciones de Lambda en Rust - AWS Lambda

DEfinir el controlador de funciones de Lambda en Rust

nota

El cliente de tiempo de ejecución de Rust es un paquete experimental. Está sujeto a cambios y destinado únicamente para fines de evaluación.

El controlador de la función de Lambda es el método del código de la función que procesa eventos. Cuando se invoca una función, Lambda ejecuta el método del controlador. La función se ejecuta hasta que el controlador devuelve una respuesta, se cierra o se agota el tiempo de espera.

Conceptos básicos del controlador de Rust

Escriba el código de la función de Lambda como un ejecutable de Rust. Implemente el código de función del controlador y una función principal e incluya lo siguiente:

ejemplo — Controlador de Rust que procesa eventos JSON

El siguiente ejemplo utiliza la caja serde_json para procesar eventos JSON básicos:

use lambda_runtime::{service_fn, LambdaEvent, Error}; use serde_json::{json, Value}; async fn handler(event: LambdaEvent<Value>) -> Result<Value, Error> { let payload = event.payload; let first_name = payload["firstName"].as_str().unwrap_or("world"); Ok(json!({ "message": format!("Hello, {first_name}!") })) } #[tokio::main] async fn main() -> Result<(), Error> { lambda_runtime::run(service_fn(handler)).await }

Tenga en cuenta lo siguiente:

  • use: importa las bibliotecas que necesita la función de Lambda.

  • async fn main: el punto de entrada que ejecuta el código de la función de Lambda. El cliente de tiempo de ejecución de Rust utiliza Tokio como un tiempo de ejecución asincrónico, por lo que debe anotar la función principal con #[tokio::main].

  • async fn handler(event: LambdaEvent<Value>) -> Result<Value,Error>: esta es la firma del controlador de Lambda. Incluye el código que se ejecuta cuando se invoca la función.

    • LambdaEvent<Value>: este es un tipo genérico que describe el evento recibido por el tiempo de ejecución de Lambda, así como el contexto de la función de Lambda.

    • Result<Value, Error>: la función devuelve un tipo Result. Si la función se ejecuta correctamente, el resultado es un valor JSON. Si la función no se ejecuta correctamente, el resultado es un error.

Uso del estado compartido

Es posible declarar variables compartidas independientes del código de controlador de la función de Lambda. Estas variables pueden ayudarlo a cargar la información de estado durante Fase "init", antes de que la función reciba cualquier evento.

ejemplo — Compartir el cliente de Amazon S3 entre instancias de funciones

Tenga en cuenta lo siguiente:

  • use aws_sdk_s3::Client: este ejemplo requiere que agregue aws-sdk-s3 = "0.26.0" a la lista de dependencias del archivo Cargo.toml.

  • aws_config::from_env: este ejemplo requiere que agregue aws-config = "0.55.1" a la lista de dependencias del archivo Cargo.toml.

use aws_sdk_s3::Client; use lambda_runtime::{service_fn, Error, LambdaEvent}; use serde::{Deserialize, Serialize}; #[derive(Deserialize)] struct Request { bucket: String, } #[derive(Serialize)] struct Response { keys: Vec<String>, } async fn handler(client: &Client, event: LambdaEvent<Request>) -> Result<Response, Error> { let bucket = event.payload.bucket; let objects = client.list_objects_v2().bucket(bucket).send().await?; let keys = objects .contents() .map(|s| s.iter().flat_map(|o| o.key().map(String::from)).collect()) .unwrap_or_default(); Ok(Response { keys }) } #[tokio::main] async fn main() -> Result<(), Error> { let shared_config = aws_config::from_env().load().await; let client = Client::new(&shared_config); let shared_client = &client; lambda_runtime::run(service_fn(move |event: LambdaEvent<Request>| async move { handler(&shared_client, event).await })) .await }

Prácticas recomendadas de codificación para las funciones de Lambda en Rust

Siga las directrices de la siguiente lista para utilizar las prácticas recomendadas de codificación al crear sus funciones de Lambda:

  • Separe el controlador de Lambda de la lógica del núcleo. Esto le permite probar las distintas unidades de la función con mayor facilidad.

  • Minimice la complejidad de las dependencias. Son preferibles los marcos de trabajo más sencillos, ya que se cargan rápidamente al arrancar el entorno de ejecución.

  • Minimice el tamaño del paquete de implementación de acuerdo con las necesidades de su tiempo de ejecución. Esto reducirá la cantidad de tiempo que tarda el paquete de implementación en descargarse y desempaquetarse antes de la invocación.

  • Reutilice el entorno de ejecución para mejorar el rendimiento de la función. Inicialice los clientes de SDK y las conexiones de base de datos fuera del controlador de funciones y almacene localmente en caché los recursos estáticos en el directorio /tmp. Las invocaciones posteriores procesadas por la misma instancia de su función pueden reutilizar estos recursos. Esto ahorra costes al reducir el tiempo de ejecución de la función.

    Para evitar posibles filtraciones de datos entre las invocaciones, no utilice el entorno de ejecución para almacenar datos de usuario, eventos u otra información con implicaciones de seguridad. Si su función se basa en un estado mutable que no se puede almacenar en la memoria dentro del controlador, considere crear una función independiente o versiones independientes de una función para cada usuario.

  • Utilice una directiva keep-alive para mantener conexiones persistentes. Lambda purga las conexiones inactivas a lo largo del tiempo. Si intenta reutilizar una conexión inactiva al invocar una función, se producirá un error de conexión. Para mantener la conexión persistente, use la directiva keep-alive asociada al tiempo de ejecución. Para ver un ejemplo, consulte Reutilización de conexiones con Keep-Alive en Node.js.

  • Utilice variables de entorno para pasar parámetros operativos a su función. Por ejemplo, si está escribiendo en un bucket de Amazon S3, en lugar de codificar de forma rígida el nombre del bucket, configúrelo como una variable de entorno.

  • Evite utilizar código recursivo en la función de Lambda que haga que esta llame a sí misma automáticamente hasta que se cumplan ciertos criterios arbitrarios. Esto podría producir un volumen no intencionado de invocaciones de la función y costos elevados. Si lo hace accidentalmente, establezca la simultaneidad reservada de funciones en 0 para limitar inmediatamente todas las invocaciones de la función mientras actualiza el código.

  • No utilice API no documentadas y no públicas en el código de la función de Lambda. Para tiempos de ejecución administrados de AWS Lambda, Lambda aplica periódicamente actualizaciones funcionales y de seguridad a las API internas de Lambda. Estas actualizaciones de las API internas pueden ser incompatibles con versiones anteriores, lo que conlleva consecuencias no deseadas, como errores de invocación si su función depende de estas API no públicas. Consulte la referencia de la API para obtener una lista de las API disponibles públicamente.

  • Escriba el código idempotente. Escribir el código idempotente para las funciones garantiza que los eventos duplicados se gestionen de la misma manera. El código debe validar y gestionar correctamente los eventos duplicados. Para obtener más información, consulte ¿Cómo puedo hacer que mi función de Lambda sea idempotente?.