View a markdown version of this page

Node.js environnement d'exécution pour les instances gérées Lambda - 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.

Node.js environnement d'exécution pour les instances gérées Lambda

Pour les Node.js environnements d'exécution, les instances gérées Lambda utilisent des threads de travail avec une exécution await basée surasync/pour gérer les demandes simultanées. L'initialisation de la fonction se produit une fois par thread de travail. Les appels simultanés sont gérés selon deux dimensions : les threads de travail fournissent le parallélisme entre les vCPU et l'exécution asynchrone assure la simultanéité au sein de chaque thread. Chaque demande simultanée gérée par le même thread de travail partage le même objet de gestionnaire et le même état global, ce qui nécessite une gestion sécurisée lors de plusieurs demandes simultanées.

Simultanéité maximum

Le nombre maximum de requêtes simultanées que Lambda envoie à chaque environnement d'exécution est contrôlé par le PerExecutionEnvironmentMaxConcurrency paramètre de la configuration de la fonction. Il s'agit d'un paramètre facultatif et la valeur par défaut varie en fonction de l'exécution. Pour les Node.js environnements d'exécution, la valeur par défaut est de 64 requêtes simultanées par processeur virtuel, ou vous pouvez configurer votre propre valeur. Lambda ajuste automatiquement le nombre de demandes simultanées jusqu'au maximum configuré en fonction de la capacité de chaque environnement d'exécution à absorber ces demandes.

En Node.js effet, le nombre de requêtes simultanées que chaque environnement d'exécution peut traiter est déterminé par le nombre de threads de travail et la capacité de chaque thread de travail à traiter les demandes simultanées de manière asynchrone. Le nombre par défaut de threads de travail est déterminé par le nombre de vCPU disponibles, ou vous pouvez configurer le nombre de threads de travail en définissant la variable d'AWS_LAMBDA_NODEJS_WORKER_COUNTenvironnement. Nous vous recommandons d'utiliser des gestionnaires de fonctions asynchrones car cela permet de traiter plusieurs demandes par thread de travail. Si votre gestionnaire de fonctions est synchrone, chaque thread de travail ne peut traiter qu'une seule demande à la fois.

Création de fonctions pour la multisimultanéité

Avec un gestionnaire de fonctions asynchrone, chaque worker d'exécution traite plusieurs demandes simultanément. Les objets globaux sont partagés entre plusieurs demandes simultanées. Pour les objets mutables, évitez d'utiliser l'état global ou l'utilisationAsyncLocalStorage.

AWS Les clients du SDK sont asynchrones et ne nécessitent aucune manipulation particulière.

Exemple : État global

Le code suivant utilise un objet global qui est muté dans le gestionnaire de fonctions. Ce n'est pas sécurisé pour l'asynchronisation.

let state = { currentUser: null, requestData: null }; export const handler = async (event, context) => { state.currentUser = event.userId; state.requestData = event.data; await processData(state.requestData); // state.currentUser might now belong to a different request return { user: state.currentUser }; };

L'initialisation de l'stateobjet dans le gestionnaire de fonctions permet d'éviter le partage de l'état global.

export const handler = async (event, context) => { let state = { currentUser: event.userId, requestData: event.data }; await processData(state.requestData); return { user: state.currentUser }; };

Exemple : connexions à une base de données

Le code suivant utilise un objet client partagé qui est partagé entre plusieurs invocations. Selon la bibliothèque de connexion utilisée, cela peut ne pas être sécurisé en matière de simultanéité.

const { Client } = require('pg'); // Single connection created at init time const client = new Client({ host: process.env.DB_HOST, database: process.env.DB_NAME, user: process.env.DB_USER, password: process.env.DB_PASSWORD }); // Connect once during cold start client.connect(); exports.handler = async (event) => { // Multiple parallel invocations share this single connection = BAD // With multi-concurrent Lambda, queries will collide const result = await client.query('SELECT * FROM users WHERE id = $1', [event.userId]); return { statusCode: 200, body: JSON.stringify(result.rows[0]) }; };

Une approche sûre en matière de concurrence consiste à utiliser un pool de connexions. Le pool utilise une connexion distincte pour chaque requête de base de données simultanée.

const { Pool } = require('pg'); // Connection pool created at init time const pool = new Pool({ host: process.env.DB_HOST, database: process.env.DB_NAME, user: process.env.DB_USER, password: process.env.DB_PASSWORD, max: 20, // Max connections in pool idleTimeoutMillis: 30000, connectionTimeoutMillis: 2000 }); exports.handler = async (event) => { // Pool gives each parallel invocation its own connection const result = await pool.query('SELECT * FROM users WHERE id = $1', [event.userId]); return { statusCode: 200, body: JSON.stringify(result.rows[0]) }; };

Node.js 22 gestionnaires basés sur les rappels

Lorsque vous utilisez Node.js 22, vous ne pouvez pas utiliser de gestionnaire de fonctions basé sur des rappels avec les instances gérées Lambda. Callback-based les gestionnaires ne sont pris en charge que pour les fonctions Lambda (par défaut). Pour les versions Node.js 24 et ultérieures, les gestionnaires de fonctions basés sur les rappels sont obsolètes pour les instances Lambda (par défaut) et Lambda Managed Instances.

Utilisez plutôt un gestionnaire de async fonctions lorsque vous utilisez des instances gérées Lambda. Pour plus d'informations, voir Définir le gestionnaire de fonctions Lambda dans. Node.js

Répertoire /tmp partagé

Le /tmp répertoire est partagé entre toutes les demandes simultanées de l'environnement d'exécution. Les écritures simultanées dans le même fichier peuvent entraîner une corruption des données, par exemple si un autre processus remplace le fichier. Pour résoudre ce problème, implémentez le verrouillage des fichiers partagés ou utilisez des noms de fichiers uniques par demande pour éviter les conflits. N'oubliez pas de nettoyer les fichiers inutiles pour ne pas épuiser l'espace disponible.

Logging

L'entrelacement des journaux (les entrées de journal provenant de différentes demandes sont entrelacées dans les journaux) est normal dans les systèmes multisimultanés. Les fonctions utilisant des instances gérées Lambda utilisent toujours le format de journal JSON structuré introduit avec les contrôles de journalisation avancés. Ce format inclut lerequestId, permettant de corréler les entrées du journal à une seule demande. Lorsque vous utilisez l'consoleenregistreur, il requestId est automatiquement inclus dans chaque entrée du journal. Pour plus d'informations, voirUtilisation des contrôles de journalisation avancés Lambda avec Node.js.

Les bibliothèques de journalisation tierces les plus populaires, telles que Winston, incluent généralement la prise en charge de l'utilisation de la console pour la sortie des journaux.

Contexte de la requête

Using context.awsRequestId fournit un accès asynchrone sécurisé à l'ID de demande pour la demande en cours.

Utilisez-le context.xRayTraceId pour accéder à l'ID de X-Ray trace. Cela fournit un accès sécurisé en cas de concurrence à l'ID de trace de la demande en cours. Lambda ne prend pas en charge la variable d'_X_AMZN_TRACE_IDenvironnement avec les instances gérées Lambda. L'ID de X-Ray trace est automatiquement propagé lors de l'utilisation du AWS SDK.

Utilisez-le context.getRemainingTimeInMillis() pour détecter les délais d'attente. Pour plus d’informations, consultez Gestion des erreurs et restauration.

Exemple : gestion des délais

Vérifiez le temps restant avant chaque unité de travail et arrêtez le traitement avant le déclenchement du timeout. Configurez en BUFFER_MS fonction de la durée prévue de votre prochaine partie de travail.

const BUFFER_MS = 2000; // Configure based on your next chunk of work exports.handler = async (event, context) => { for (const item of event.items) { if (context.getRemainingTimeInMillis() < BUFFER_MS) return { statusCode: 206, body: "Timeout approaching, stopping early" }; await processItem(item); } return { statusCode: 200, body: "Done" }; };

Exemple : Propagation des délais aux appels en aval

Lorsque vous passez des appels vers des services en aval, répartissez le temps restant sous forme de délai d'attente pour éviter de vous accrocher à des appels réseau qui dureraient plus longtemps que votre appel :

const { S3Client, GetObjectCommand } = require("@aws-sdk/client-s3"); const client = new S3Client({}); exports.handler = async (event, context) => { const timeout = Math.max(1000, context.getRemainingTimeInMillis() - 500); const response = await client.send( new GetObjectCommand({ Bucket: "my-bucket", Key: "my-key" }), { abortSignal: AbortSignal.timeout(timeout) } ); return { statusCode: 200, body: "Done" }; };

Initialisation et arrêt

L'initialisation de la fonction se produit une fois par thread de travail. Il est possible que des entrées de journal se répètent si votre fonction émet des journaux lors de l'initialisation.

Pour les fonctions Lambda dotées d'extensions, l'environnement d'exécution émet un signal SIGTERM lors de l'arrêt. Ce signal est utilisé par les extensions pour déclencher des tâches de nettoyage, telles que le vidage des buffers. Les fonctions Lambda (par défaut) avec des extensions peuvent également s'abonner au signal SIGTERM en utilisant. process.on() Ceci n'est pas pris en charge pour les fonctions utilisant des instances gérées Lambda car il process.on() ne peut pas être utilisé avec des threads de travail. Pour en savoir plus sur le cycle de vie de l'environnement d'exécution, veuillez consulter Comprendre le cycle de vie de l’environnement d’exécution Lambda.

Versions de dépendance

Les instances gérées Lambda nécessitent les versions de package minimales suivantes :

  • AWS SDK pour JavaScript v3 : version 3.933.0 ou ultérieure

  • AWS X-Ray SDK pour Node.js : version 3.12.0 ou ultérieure

  • AWS Distribution pour OpenTelemetry - Instrumentation pour JavaScript : version 0.8.0 ou ultérieure

  • Powertools pour AWS Lambda (TypeScript) : version 2.29.0 ou ultérieure

Outils électriques pour AWS Lambda () TypeScript

Powertools for AWS Lambda (TypeScript) est compatible avec les instances gérées Lambda et fournit des utilitaires pour la journalisation, le suivi, les métriques, etc. Pour plus d'informations, consultez Powertools for AWS Lambda ()TypeScript.

Étapes suivantes