Sélectionner vos préférences de cookies

Nous utilisons des cookies essentiels et des outils similaires qui sont nécessaires au fonctionnement de notre site et à la fourniture de nos services. Nous utilisons des cookies de performance pour collecter des statistiques anonymes afin de comprendre comment les clients utilisent notre site et d’apporter des améliorations. Les cookies essentiels ne peuvent pas être désactivés, mais vous pouvez cliquer sur « Personnaliser » ou « Refuser » pour refuser les cookies de performance.

Si vous êtes d’accord, AWS et les tiers approuvés utiliseront également des cookies pour fournir des fonctionnalités utiles au site, mémoriser vos préférences et afficher du contenu pertinent, y compris des publicités pertinentes. Pour accepter ou refuser tous les cookies non essentiels, cliquez sur « Accepter » ou « Refuser ». Pour effectuer des choix plus détaillés, cliquez sur « Personnaliser ».

Définir les gestionnaires de fonctions Lambda dans Rust

Mode de mise au point
Définir les gestionnaires de fonctions Lambda dans Rust - AWS Lambda

Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.

Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.

Note

Le client d’exécution Rust est un package expérimental. Il est susceptible d’être modifié et n’est destiné qu’à des fins d’évaluation.

Le gestionnaire de fonction Lambda est la méthode dans votre code de fonction qui traite les événements. Lorsque votre fonction est invoquée, Lambda exécute la méthode du gestionnaire. Votre fonction s’exécute jusqu’à ce que le gestionnaire renvoie une réponse, se ferme ou expire.

Cette page décrit comment utiliser les gestionnaires de fonctions Lambda dans Rust, y compris l'initialisation du projet, les conventions de dénomination et les meilleures pratiques. Cette page inclut également un exemple de fonction Rust Lambda qui prend des informations sur une commande, produit un reçu sous forme de fichier texte et place ce fichier dans un bucket Amazon Simple Storage Service (S3). Pour plus d'informations sur le déploiement de votre fonction après l'avoir écrite, consultezDéploiement de fonctions Lambda Rust avec des archives de fichiers .zip.

Configuration de votre projet de gestionnaire Rust

Lorsque vous travaillez avec des fonctions Lambda dans Rust, le processus consiste à écrire votre code, à le compiler et à déployer les artefacts compilés sur Lambda. Le moyen le plus simple de configurer un projet de gestionnaire Lambda dans Rust est d'utiliser le AWS Lambda Runtime for Rust. Malgré son nom, le AWS Lambda Runtime for Rust n'est pas un environnement d'exécution géré au même sens que dans Lambda pour Python, Java ou Node.js. Au lieu de cela, le AWS Lambda Runtime for Rust est un crate (lambda_runtime) qui permet d'écrire des fonctions Lambda dans Rust et de s'interfacer avec l'environnement d'exécution AWS Lambda de celui-ci.

Utilisez la commande suivante pour installer le AWS Lambda Runtime for Rust :

cargo install cargo-lambda

Une fois l'installation réussiecargo-lambda, utilisez la commande suivante pour initialiser un nouveau projet de gestionnaire de fonctions Rust Lambda :

cargo lambda new example-rust

Lorsque vous exécutez cette commande, l'interface de ligne de commande (CLI) vous pose quelques questions concernant votre fonction Lambda :

  • Fonction HTTP — Si vous avez l'intention d'appeler votre fonction via API Gateway ou une URL de fonction, répondez Oui. Dans le cas contraire, répondez Non. Dans l'exemple de code de cette page, nous invoquons notre fonction avec un événement JSON personnalisé. Nous répondons donc Non.

  • Type d'événement : si vous avez l'intention d'utiliser une forme d'événement prédéfinie pour appeler votre fonction, sélectionnez le type d'événement attendu approprié. Dans le cas contraire, laissez cette option vide. Dans l'exemple de code de cette page, nous invoquons notre fonction avec un événement JSON personnalisé. Nous laissons donc cette option vide.

Une fois la commande exécutée avec succès, entrez dans le répertoire principal de votre projet :

cd example-rust

Cette commande génère un generic_handler.rs fichier et un main.rs autre dans le src répertoire. Il generic_handler.rs peut être utilisé pour personnaliser un gestionnaire d'événements générique. Le main.rs fichier contient la logique principale de votre application. Le Cargo.toml fichier contient des métadonnées relatives à votre package et répertorie ses dépendances externes.

Exemple de code de fonction Rust Lambda

L'exemple de code de fonction Rust Lambda suivant prend des informations sur une commande, produit un reçu de fichier texte et place ce fichier dans un compartiment Amazon S3.

Exemple Fonction Lambda main.rs
use aws_sdk_s3::{Client, primitives::ByteStream}; use lambda_runtime::{run, service_fn, Error, LambdaEvent}; use serde::{Deserialize, Serialize}; use serde_json::Value; use std::env; #[derive(Deserialize, Serialize)] struct Order { order_id: String, amount: f64, item: String, } async fn function_handler(event: LambdaEvent<Value>) -> Result<String, Error> { let payload = event.payload; // Deserialize the incoming event into Order struct let order: Order = serde_json::from_value(payload)?; let bucket_name = env::var("RECEIPT_BUCKET") .map_err(|_| "RECEIPT_BUCKET environment variable is not set")?; let receipt_content = format!( "OrderID: {}\nAmount: ${:.2}\nItem: {}", order.order_id, order.amount, order.item ); let key = format!("receipts/{}.txt", order.order_id); let config = aws_config::load_defaults(aws_config::BehaviorVersion::latest()).await; let s3_client = Client::new(&config); upload_receipt_to_s3(&s3_client, &bucket_name, &key, &receipt_content).await?; Ok("Success".to_string()) } async fn upload_receipt_to_s3( client: &Client, bucket_name: &str, key: &str, content: &str, ) -> Result<(), Error> { client .put_object() .bucket(bucket_name) .key(key) .body(ByteStream::from(content.as_bytes().to_vec())) // Fixed conversion .content_type("text/plain") .send() .await?; Ok(()) } #[tokio::main] async fn main() -> Result<(), Error> { run(service_fn(function_handler)).await }

Ce fichier main.rs comprend les sections suivantes :

  • useinstructions : Utilisez-les pour importer les caisses Rust et les méthodes requises par votre fonction Lambda.

  • #[derive(Deserialize, Serialize)]: Définissez la forme de l'événement d'entrée attendu dans cette structure Rust.

  • async fn function_handler(event: LambdaEvent<Value>) -> Result<String, Error> : il s’agit de la méthode de gestion principale, qui contient la logique principale de votre application.

  • async fn upload_receipt_to_s3 (...): il s'agit d'une méthode auxiliaire référencée par la function_handler méthode principale.

  • #[tokio::main]: Il s'agit d'une macro qui marque le point d'entrée d'un programme Rust. Il met également en place un environnement d'exécution Tokio, qui permet à votre main() méthode d'utiliserasync/awaitet de s'exécuter de manière asynchrone.

  • async fn main() -> Result<(), Error>: La main() fonction est le point d'entrée de votre code. Dans celui-ci, nous spécifions function_handler comme méthode de gestion principale.

Le Cargo.toml fichier suivant accompagne cette fonction.

[package] name = "example-rust" version = "0.1.0" edition = "2024" [dependencies] aws-config = "1.5.18" aws-sdk-s3 = "1.78.0" lambda_runtime = "0.13.0" serde = { version = "1", features = ["derive"] } serde_json = "1" tokio = { version = "1", features = ["full"] }

Exemple de fichier Cargo.toml

Le Cargo.toml fichier suivant accompagne cette fonction.

[package] name = "example-rust" version = "0.1.0" edition = "2024" [dependencies] aws-config = "1.5.18" aws-sdk-s3 = "1.78.0" lambda_runtime = "0.13.0" serde = { version = "1", features = ["derive"] } serde_json = "1" tokio = { version = "1", features = ["full"] }

Pour que cette fonction fonctionne correctement, son rôle d'exécution doit autoriser l's3:PutObjectaction. Assurez-vous également de définir la variable d’environnement RECEIPT_BUCKET. Après une invocation réussie, le compartiment Amazon S3 doit contenir un fichier de reçu.

Définitions de classe valides pour les gestionnaires Rust

Dans la plupart des cas, les signatures du gestionnaire Lambda que vous définissez dans Rust auront le format suivant :

async fn function_handler(event: LambdaEvent<T>) -> Result<U, Error>

Pour ce gestionnaire :

  • Le nom de ce gestionnaire estfunction_handler.

  • L'entrée singulière du gestionnaire est un événement et est de typeLambdaEvent<T>.

    • LambdaEventest un emballage qui vient de la lambda_runtime caisse. L'utilisation de ce wrapper vous donne accès à l'objet de contexte, qui inclut des métadonnées spécifiques à Lambda, telles que l'ID de demande de l'invocation.

    • Test le type d'événement désérialisé. Par exemple, cela peut être le casserde_json::Value, ce qui permet au gestionnaire de prendre en compte n'importe quelle entrée JSON générique. Il peut également s'agir d'un type comme ApiGatewayProxyRequest si votre fonction attend un type d'entrée spécifique et prédéfini.

  • Le type de retour du gestionnaire estResult<U, Error>.

    • Uest le type de sortie désérialisé. Udoit implémenter le serde::Serialize trait afin que Lambda puisse convertir la valeur de retour en JSON. Par exemple, il U peut s'agir d'un type simple tel que Stringserde_json::Value, ou d'une structure personnalisée tant qu'il est Serialize implémenté. Lorsque votre code atteint une instruction Ok (U), cela indique une exécution réussie et votre fonction renvoie une valeur de typeU.

    • Lorsque votre code rencontre une erreur (c'est-à-direErr(Error)), votre fonction enregistre l'erreur dans Amazon CloudWatch et renvoie une réponse d'erreur de typeError.

Dans notre exemple, la signature du gestionnaire ressemble à ce qui suit :

async fn function_handler(event: LambdaEvent<Value>) -> Result<String, Error>

Les autres signatures de gestionnaire valides peuvent comporter les éléments suivants :

  • Omission du LambdaEvent wrapper — Si vous omettezLambdaEvent, vous perdez l'accès à l'objet de contexte Lambda dans votre fonction. Voici un exemple de ce type de signature :

    async fn handler(event: serde_json::Value) -> Result<String, Error>
  • Utilisation du type d'unité comme entrée — Pour Rust, vous pouvez utiliser le type d'unité pour représenter une entrée vide. Ceci est couramment utilisé pour les fonctions avec des invocations périodiques et planifiées. Voici un exemple de ce type de signature :

    async fn handler(): ()) -> Result<Value, Error>

Convention de nommage du gestionnaire

Les gestionnaires Lambda dans Rust n'ont pas de restrictions de dénomination strictes. Bien que vous puissiez utiliser n'importe quel nom pour votre gestionnaire, les noms de fonctions dans Rust sont généralement disponibles. snake_case

Pour les applications plus petites, comme dans cet exemple, vous pouvez utiliser un seul main.rs fichier pour contenir l'ensemble de votre code. Pour les projets plus importants, main.rs il doit contenir le point d'entrée de votre fonction, mais vous pouvez avoir des fichiers supplémentaires pour séparer votre code en modules logiques. Par exemple, vous pouvez avoir la structure de fichier suivante :

/example-rust │── src/ │ ├── main.rs # Entry point │ ├── handler.rs # Contains main handler │ ├── services.rs # [Optional] Back-end service calls │ ├── models.rs # [Optional] Data models │── Cargo.toml

Définition et accès à l’objet d’événement d’entrée

JSON est le format d’entrée le plus courant et standard pour les fonctions Lambda. Dans cet exemple, la fonction exige une entrée similaire à l’exemple suivant :

{ "order_id": "12345", "amount": 199.99, "item": "Wireless Headphones" }

Dans Rust, vous pouvez définir la forme de l'événement d'entrée attendu dans une structure. Dans cet exemple, nous définissons la structure suivante pour représenter un Order :

#[derive(Deserialize, Serialize)] struct Order { order_id: String, amount: f64, item: String, }

Cette structure correspond à la forme d’entrée attendue. Dans cet exemple, la #[derive(Deserialize, Serialize)] macro génère automatiquement du code pour la sérialisation et la désérialisation. Cela signifie que nous pouvons désérialiser le type JSON d'entrée générique dans notre structure à l'aide de la méthode. serde_json::from_value() Ceci est illustré dans les premières lignes du gestionnaire :

async fn function_handler(event: LambdaEvent<Value>) -> Result<String, Error> { let payload = event.payload; // Deserialize the incoming event into Order struct let order: Order = serde_json::from_value(payload)?; ... }

Vous pouvez ensuite accéder aux champs de l'objet. Par exemple, order.order_id récupère la valeur de order_id à partir de l’entrée d’origine.

Types d'événements d'entrée prédéfinis

De nombreux types d'événements d'entrée prédéfinis sont disponibles dans la aws_lambda_events caisse. Par exemple, si vous avez l'intention d'appeler votre fonction avec API Gateway, y compris l'importation suivante :

use aws_lambda_events::event::apigw::ApiGatewayProxyRequest;

Assurez-vous ensuite que votre gestionnaire principal utilise la signature suivante :

async fn handler(event: LambdaEvent<ApiGatewayProxyRequest>) -> Result<String, Error> { let body = event.payload.body.unwrap_or_default(); ... }

Reportez-vous à la caisse aws_lambda_events pour plus d'informations sur les autres types d'événements d'entrée prédéfinis.

Accès et utilisation de l’objet de contexte Lambda

L’objet de contexte Lambda contient des informations sur l’invocation, la fonction et l’environnement d’exécution. Dans Rust, le LambdaEvent wrapper inclut l'objet de contexte. Par exemple, vous pouvez utiliser l'objet de contexte pour récupérer l'ID de demande de l'appel en cours à l'aide du code suivant :

async fn function_handler(event: LambdaEvent<Value>) -> Result<String, Error> { let request_id = event.context.request_id; ... }

Pour plus d’informations sur la copie d’objets, consultez Utilisation de l’objet de contexte Lambda pour récupérer les informations de la fonction Rust.

En utilisant le Kit AWS SDK pour Rust dans votre gestionnaire

Vous utiliserez souvent les fonctions Lambda pour interagir avec d'autres AWS ressources ou pour les mettre à jour. Le moyen le plus simple d'interagir avec ces ressources est d'utiliser le Kit AWS SDK pour Rust.

Pour ajouter des dépendances du SDK à votre fonction, ajoutez-les dans votre Cargo.toml fichier. Nous vous recommandons de n'ajouter que les bibliothèques dont vous avez besoin pour votre fonction. Dans l'exemple de code précédent, nous avons utilisé leaws_sdk_s3::Client. Dans le Cargo.toml fichier, vous pouvez ajouter cette dépendance en ajoutant la ligne suivante sous la [dependencies] section :

aws-sdk-s3 = "1.78.0"
Note

Il ne s'agit peut-être pas de la version la plus récente. Choisissez la version adaptée à votre application.

Importez ensuite les dépendances directement dans votre code :

use aws_sdk_s3::{Client, primitives::ByteStream};

L'exemple de code initialise ensuite un client Amazon S3 comme suit :

let config = aws_config::load_defaults(aws_config::BehaviorVersion::latest()).await; let s3_client = Client::new(&config);

Après avoir initialisé votre client SDK, vous pouvez l'utiliser pour interagir avec d'autres AWS services. L'exemple de code appelle l'PutObjectAPI Amazon S3 dans la fonction d'upload_receipt_to_s3assistance.

Accès aux variables d’environnement

Dans le code de votre gestionnaire, vous pouvez référencer n’importe quelle variable d’environnement à l’aide de la méthode env::var. Dans cet exemple, nous référençons la variable d’environnement RECEIPT_BUCKET définie à l’aide de la ligne de code suivante :

let bucket_name = env::var("RECEIPT_BUCKET") .map_err(|_| "RECEIPT_BUCKET environment variable is not set")?;

Utilisation de l’état partagé

Vous pouvez déclarer des variables partagées indépendantes du code du gestionnaire de votre fonction Lambda. Ces variables peuvent vous aider à charger des informations d’état pendant le Phase d’initialisation, avant que votre fonction ne reçoive des événements. Par exemple, vous pouvez modifier le code de cette page pour utiliser l'état partagé lors de l'initialisation du client Amazon S3 en mettant à jour la main fonction et la signature du gestionnaire :

async fn function_handler(client: &Client, event: LambdaEvent<Value>) -> Result<String, Error> { ... upload_receipt_to_s3(client, &bucket_name, &key, &receipt_content).await?; ... } ... #[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

Pratiques exemplaires en matière de code pour les fonctions Lambda Rust

Respectez les directives de la liste suivante pour utiliser les pratiques exemplaires de codage lors de la création de vos fonctions Lambda :

  • Séparez le gestionnaire Lambda de votre logique principale. Cela vous permet de créer une fonction testable plus unitaire.

  • Réduisez la complexité de vos dépendances. Privilégiez les infrastructures plus simples qui se chargent rapidement au démarrage de l’environnement d’exécution.

  • Réduisez la taille de votre package de déploiement selon ses besoins d’exécution. Cela contribue à réduire le temps nécessaire au téléchargement et à la décompression de votre package de déploiement avant l’invocation.

  • Tirez parti de la réutilisation de l’environnement d’exécution pour améliorer les performances de votre fonction. Initialisez les clients SDK et les connexions à la base de données en dehors du gestionnaire de fonctions et mettez en cache les actifs statiques localement dans le répertoire /tmp. Les invocations ultérieures traitées par la même instance de votre fonction peuvent réutiliser ces ressources. Cela permet d’économiser des coûts, tout en réduisant le temps d’exécution de la fonction.

    Pour éviter des éventuelles fuites de données entre les invocations, n’utilisez pas l’environnement d’exécution pour stocker des données utilisateur, des événements ou d’autres informations ayant un impact sur la sécurité. Si votre fonction repose sur un état réversible qui ne peut pas être stocké en mémoire dans le gestionnaire, envisagez de créer une fonction distincte ou des versions distinctes d’une fonction pour chaque utilisateur.

  • Utilisez une directive keep-alive pour maintenir les connexions persistantes. Lambda purge les connexions inactives au fil du temps. Si vous tentez de réutiliser une connexion inactive lorsque vous invoquez une fonction, cela entraîne une erreur de connexion. Pour maintenir votre connexion persistante, utilisez la directive Keep-alive associée à votre environnement d’exécution. Pour obtenir un exemple, consultez Réutilisation des connexions avec Keep-Alive dans Node.js.

  • Utilisez des variables d’environnement pour transmettre des paramètres opérationnels à votre fonction. Par exemple, si vous écrivez dans un compartiment Amazon S3 au lieu de coder en dur le nom du compartiment dans lequel vous écrivez, configurez le nom du compartiment comme variable d’environnement.

  • Évitez d’utiliser des invocations récursives dans votre fonction Lambda, lorsque la fonction s’invoque elle-même ou démarre un processus susceptible de l’invoquer à nouveau. Cela peut entraîner un volume involontaire d’invocations de fonction et des coûts accrus. Si vous constatez un volume involontaire d’invocations, définissez immédiatement la simultanéité réservée à la fonction sur 0 afin de limiter toutes les invocations de la fonction, pendant que vous mettez à jour le code.

  • N'utilisez pas de code non documenté ni public APIs dans votre code de fonction Lambda. Pour les AWS Lambda environnements d'exécution gérés, Lambda applique régulièrement des mises à jour de sécurité et fonctionnelles aux applications internes de Lambda. APIs Ces mises à jour internes de l'API peuvent être rétroincompatibles, ce qui peut entraîner des conséquences imprévues, telles que des échecs d'invocation si votre fonction dépend de ces mises à jour non publiques. APIs Consultez la référence de l'API pour obtenir une liste des API accessibles au public APIs.

  • Écriture du code idempotent. L’écriture de code idempotent pour vos fonctions garantit ne gestion identique des événements dupliqués. Votre code doit valider correctement les événements et gérer correctement les événements dupliqués. Pour de plus amples informations, veuillez consulterComment faire en sorte que ma fonction Lambda soit idempotente ?.

Rubrique suivante :

Contexte

Rubrique précédente :

Création avec Rust
ConfidentialitéConditions d'utilisation du sitePréférences de cookies
© 2025, Amazon Web Services, Inc. ou ses affiliés. Tous droits réservés.