Runtime Node.js 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.

Runtime Node.js pour les instances gérées Lambda

Pour les environnements d'exécution de Node.js, les instances gérées Lambda utilisent des threads de travail async avec une exécution basée surawait/pour gérer les demandes simultanées. L'initialisation de la fonction a lieu une fois par thread de travail. Les invocations simultanées sont gérées selon deux dimensions : les threads de travail assurent le parallélisme entre vCPUs, et l'exécution asynchrone assure la simultanéité au sein de chaque thread. Chaque demande simultanée traité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 un traitement sécurisé dans le cadre de plusieurs demandes simultanées.

Simultanéité maximum

Le nombre maximum de demandes simultanées que Lambda envoie à chaque environnement d'exécution est contrôlé par le PerExecutionEnvironmentMaxConcurrency paramètre de configuration de la fonction. Il s'agit d'un paramètre facultatif, et la valeur par défaut varie en fonction du temps d'exécution. Pour les environnements d'exécution de Node.js, la valeur par défaut est de 64 requêtes simultanées par vCPU, 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.

Pour Node.js, le nombre de demandes simultanées que chaque environnement d'exécution peut traiter est déterminé par le nombre de threads de travail et par 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 v CPUs disponibles, ou vous pouvez configurer le nombre de threads de travail en définissant la variable d'AWS_LAMBDA_NODEJS_WORKER_COUNTenvironnement. Nous 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 asynchrones, chaque utilisateur d'exécution traite plusieurs demandes simultanément. Les objets globaux seront partagés entre plusieurs demandes simultanées. Pour les objets mutables, évitez d'utiliser un état ou un usage AsyncLocalStorage global.

AWS Les clients du SDK sont sécurisés en mode asynchrone 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é en mode asynchrone.

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 un état global partagé.

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

Exemple : connexions à la base de données

Le code suivant utilise un objet client partagé qui est partagé entre plusieurs invocations. Selon la bibliothèque de connexions utilisée, il se peut que cela ne soit pas sûr 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 simultanéité 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 des rappels

Lorsque vous utilisez Node.js 22, vous ne pouvez pas utiliser de gestionnaire de fonctions basé sur le rappel avec les instances gérées Lambda. Les gestionnaires basés sur le rappel ne sont pris en charge que pour les fonctions Lambda (par défaut). Pour les environnements d'exécution de Node.js 24 et versions ultérieures, les gestionnaires de fonctions basés sur le rappel sont déconseillés 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, consultez la section Définir le gestionnaire de fonctions Lambda dans le fichier Node.js.

Répertoire /tmp partagé

Le /tmp répertoire est partagé entre toutes les demandes simultanées dans 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 afin d'é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 des journaux provenant de différentes demandes sont entrelacées dans des journaux) est normal dans les systèmes multiconcurrents. 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, ce qui permet 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, consultez la section Utilisation des contrôles de journalisation avancés Lambda avec Node.js.

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

Contexte de la requête

L'utilisation context.awsRequestId fournit un accès asynchrone à l'ID de demande pour la demande en cours.

context.xRayTraceIdÀ utiliser pour accéder au X-Ray Trace ID. Cela fournit un accès simultané à l'ID de trace pour la demande en cours. Lambda ne prend pas en charge la variable d'_X_AMZN_TRACE_IDenvironnement avec les instances gérées par Lambda. Le X-Ray Trace ID est automatiquement propagé lors de l'utilisation du AWS SDK.

Initialisation et arrêt

L'initialisation de la fonction a lieu une fois par thread de travail. Des entrées de journal répétées peuvent s'afficher si votre fonction émet des journaux lors de l'initialisation.

Pour les fonctions Lambda avec 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 tampons. Les fonctions Lambda (par défaut) avec 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 les threads de travail. Pour en savoir plus sur le cycle de vie de l'environnement d'exécution, consultez 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 Kit de développement X-Ray pour Node.js : version 3.12.0 ou ultérieure

  • AWS Distro 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 TypeScript Lambda ()

Powertools for AWS Lambda TypeScript () est compatible avec les instances gérées par 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