Tiempo de ejecución de Node.js para instancias administradas de Lambda
Para los tiempos de ejecución de Node.js, las instancias administradas de Lambda utilizan subprocesos de trabajo con ejecución basada en async o en await para gestionar las solicitudes simultáneas. La inicialización de la función se produce una vez por subproceso de trabajo. Las invocaciones simultáneas se gestionan en dos dimensiones: los subprocesos de trabajo proporcionan paralelismo entre las vCPU y la ejecución asíncrona proporciona concurrencia dentro de cada subproceso. Cada solicitud simultánea administrada por el mismo subproceso de trabajo comparte el mismo objeto controlador y el mismo estado global, por lo que es necesaria una gestión segura en el caso de varias solicitudes simultáneas.
Simultaneidad máxima
El número máximo de solicitudes simultáneas que envía Lambda a cada entorno de ejecución se controla mediante el ajuste PerExecutionEnvironmentMaxConcurrency de la configuración de la función. Se trata de una configuración opcional y el valor predeterminado varía en función del tiempo de ejecución. Para los tiempos de ejecución de Node.js, el valor predeterminado es de 64 solicitudes simultáneas por vCPU, o puede configurar su propio valor. Lambda ajusta automáticamente el número de solicitudes simultáneas hasta el máximo configurado en función de la capacidad de cada entorno de ejecución para absorber esas solicitudes.
En el caso de Node.js, el número de solicitudes simultáneas que puede procesar cada entorno de ejecución viene determinado por el número de subprocesos de trabajo y la capacidad de cada subproceso de trabajo para procesar solicitudes simultáneas de forma asíncrona. El número predeterminado de subprocesos de trabajo viene determinado por la cantidad de vCPU disponibles, o puede configurar la cantidad de subprocesos de trabajo configurando la variable de entorno AWS_LAMBDA_NODEJS_WORKER_COUNT. Recomendamos utilizar controladores de funciones asíncronos, ya que permiten procesar varias solicitudes por subproceso de trabajo. Si su controlador de funciones es sincrónico, cada subproceso de trabajo solo puede procesar una solicitud a la vez.
Creación de funciones para la concurrencia múltiple
Con un controlador de funciones asíncrono, cada trabajador en tiempo de ejecución procesa varias solicitudes de forma simultánea. Los objetos globales se compartirán en varias solicitudes simultáneas. En el caso de los objetos mutables, evite usar el estado global o utilice el AsyncLocalStorage.
Los clientes de AWS SDK son seguros para la modalidad asíncrona y no requieren una gestión especial.
Ejemplo: estado global
El siguiente código usa un objeto global que está mutado dentro del controlador de funciones. Esto no es seguro para el proceso de forma asíncrona.
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 }; };
La inicialización del objeto state dentro del controlador de funciones evita un estado global compartido.
export const handler = async (event, context) => { let state = { currentUser: event.userId, requestData: event.data }; await processData(state.requestData); return { user: state.currentUser }; };
Ejemplo: conexiones a bases de datos
El código siguiente utiliza un objeto de cliente compartido que se comparte entre varias invocaciones. Según la biblioteca de conexiones utilizada, es posible que no sea segura para la concurrencia.
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]) }; };
Un enfoque seguro para la concurrencia consiste en utilizar un grupo de conexiones. El grupo utiliza una conexión independiente para cada consulta simultánea de la base de datos.
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]) }; };
Controladores de Node.js 22 basados en la devolución de llamada
Cuando utiliza Node.js 22, no puede usar un controlador de funciones basado en la devolución de llamada con instancias administradas de Lambda. Los controladores basados en la devolución de llamada son compatibles solo con las funciones de Lambda (predeterminadas). Para los tiempos de ejecución de Node.js 24 y versiones posteriores, los controladores de funciones basados en la devolución de llamada están obsoletos, tanto para Lambda (predeterminado) como para las instancias administradas de Lambda.
En su lugar, utilice un controlador de funciones async cuando utilice instancias administradas de Lambda. Para obtener más información, consulte Definición de controlador de funciones de Lambda en Node.js.
Directorio /tmp compartido
El directorio /tmp se comparte entre todas las solicitudes simultáneas del entorno de ejecución. Las escrituras simultáneas en el mismo archivo pueden dañar los datos, por ejemplo, si otro proceso sobrescribe el archivo. Para solucionar este problema, implemente el bloqueo de archivos para los archivos compartidos o utilice nombres de archivo únicos por solicitud para evitar conflictos. Recuerde limpiar los archivos innecesarios para no agotar el espacio disponible.
Registro
El intercalado de registros (las entradas de registro de diferentes solicitudes se intercalan en los registros) es normal en los sistemas simultáneos múltiples. Las funciones que utilizan instancias administradas de Lambda utilizan siempre el formato de registro JSON estructurado introducido con los controles de registro avanzados. Este formato incluye el requestId, lo que permite correlacionar las entradas de registro con una sola solicitud. Cuando utiliza el registrador de la console, el requestId se incluye automáticamente en cada entrada de registro. Para obtener más información, consulte Uso de los controles de registro avanzados de Lambda con Node.js.
Las bibliotecas de registro populares de terceros, como Winston
El contexto de la solicitud
El uso del context.awsRequestId proporciona un acceso asíncrono y seguro al identificador de solicitud de la solicitud actual.
Utilice el context.xRayTraceId para acceder al identificador de seguimiento de X-Ray. Esto proporciona un acceso simultáneo y seguro al identificador de seguimiento de la solicitud actual. Lambda no admite la variable de entorno _X_AMZN_TRACE_ID con las instancias administradas de Lambda. El identificador de seguimiento de X-Ray se propaga automáticamente cuando se utiliza AWS SDK.
Inicialización y apagado
La inicialización de la función se produce una vez por subproceso de trabajo. Es posible que vea entradas de registro repetidas si su función emite registros durante la inicialización.
En el caso de las funciones de Lambda con extensiones, el entorno de ejecución emite una señal SIGTERM durante el cierre. Las extensiones utilizan esta señal para desencadenar tareas de limpieza, como vaciar los búferes. Las funciones de Lambda (predeterminadas) con extensiones también pueden suscribirse a la señal SIGTERM mediante process.on(). Esto no se admite para las funciones que utilizan instancias administradas de Lambda, ya que no se puede utilizar el process.on() con subprocesos de trabajo. Para obtener más información sobre el ciclo de vida del entorno de ejecución, consulte Descripción del ciclo de vida del entorno de ejecución de Lambda.
Versiones de dependencias
Las instancias administradas de Lambda requieren las siguientes versiones de paquete como mínimo:
-
AWS SDK para JavaScript v3: versión 3.933.0 o posterior
-
AWS X-Ray SDK para Node.js: versión 3.12.0 o posterior
-
AWS Distro para OpenTelemetry, instrumentación para JavaScript: versión 0.8.0 o posterior
-
Powertools para AWS Lambda (TypeScript): versión 2.29.0 o posterior
Powertools para AWS Lambda (TypeScript)
Powertools para AWS Lambda (TypeScript) es compatible con las instancias administradas de Lambda y proporciona utilidades para el registro, el seguimiento, las métricas y mucho más. Para obtener más información, consulte Powertools para AWS Lambda (TypeScript)
Siguientes pasos
-
Revise el tiempo de ejecución de Java para instancias administradas de Lambda.
-
Revise el tiempo de ejecución de Python para instancias administradas de Lambda.
-
Revise el tiempo de ejecución de .NET para instancias administradas de Lambda.
-
Obtenga información sobre el escalado de instancias administradas de Lambda.