Prácticas recomendadas para las funciones duraderas de Lambda
Las funciones duraderas utilizan un modelo de ejecución basado en la reproducción que requiere patrones diferentes a los de las funciones de Lambda tradicionales. Siga estas prácticas recomendadas para crear flujos de trabajo fiables y rentables.
Escritura de código determinista
Durante la reproducción, la función se ejecuta desde el principio y debe seguir la misma ruta de ejecución que la ejecución original. El código ajeno a las operaciones duraderas debe ser determinista y producir los mismos resultados con las mismas entradas.
Encapsule las operaciones no deterministas en pasos:
Generación de números al azar y UUID
Hora o marcas de tiempo actuales
Llamadas a la API externas y consultas a las bases de datos
Operaciones del sistema de archivos
Importante
No utilice variables globales ni cierre para compartir el estado entre los pasos. Transfiera los datos a través de los valores devueltos. El estado global se interrumpe durante la reproducción porque los pasos devuelven resultados en caché, pero las variables globales se restablecen.
Evite las mutaciones de cierre: las variables capturadas en los cierres pueden perder mutaciones durante la reproducción. Los pasos devuelven los resultados guardados en caché, pero las actualizaciones de variables ajenas al paso no se reproducen.
Diseño de idempotencia
Las operaciones pueden ejecutarse varias veces debido a los reintentos o a la reproducción. Las operaciones no idempotentes provocan efectos secundarios duplicados, como cobrar dos veces a los clientes o enviar varios correos electrónicos.
Utilice tokens de idempotencia: genere tokens dentro de los pasos e inclúyelos en las llamadas a la API externas para evitar la duplicación de operaciones.
Utilice la semántica de como máximo una vez: para las operaciones críticas que nunca deben duplicarse (transacciones financieras, deducciones de inventario), configure el modo de ejecución como máximo una vez.
Idempotencia de la base de datos: utilice patrones de verificación antes de escribir, actualizaciones condicionales u operaciones de modificación para evitar la duplicación de registros.
Administración del estado de manera eficiente
Cada punto de control guarda el estado en el almacenamiento persistente. Los objetos de gran tamaño aumentan los costos, ralentizan la creación de puntos de control y afectan el rendimiento. Almacene solo los datos esenciales de coordinación del flujo de trabajo.
Mantenga el estado mínimo:
Almacene los identificadores y las referencias, no los objetos completos.
Obtenga datos detallados dentro de los pasos, según sea necesario.
Utilice Amazon S3 o DynamoDB para datos de gran tamaño y pase las referencias en estado.
Evite pasar grandes cargas útiles entre pasos.
Diseñe pasos efectivos.
Los pasos son la unidad de trabajo fundamental de las funciones duraderas. Los pasos bien diseñados facilitan la comprensión, la depuración y el mantenimiento de los flujos de trabajo.
Principios de diseño de pasos:
Utilice nombres descriptivos: los nombres como
validate-orderen lugar destep1facilita la comprensión de los registros y los errores.Mantenga los nombres estáticos: no utilice nombres dinámicos con marcas de tiempo o valores al azar. Los nombres de los pasos deben ser deterministas para poder reproducirlos.
Equilibre la granularidad: divida las operaciones complejas en pasos específicos, pero evite los pasos demasiado pequeños que aumentan la sobrecarga de los puntos de control.
Operaciones relacionadas por grupo: las operaciones que deberían tener éxito o fracasar juntas pertenecen al mismo paso.
Utilice las operaciones de espera de forma eficiente.
Las operaciones de espera suspenden la ejecución sin consumir recursos ni incurrir en costos. Úselos en lugar de mantener la ejecución de Lambda.
Esperas basadas en el tiempo: utilice context.wait() para los retrasos en lugar de setTimeout o sleep.
Devoluciones de llamada externas: utilice context.waitForCallback() cuando se espera por sistemas externos. Establezca siempre tiempos de espera para evitar esperas indefinidas.
Sondeo: utilice context.waitForCondition() con un retroceso exponencial para sondear los servicios externos sin sobrecargarlos.
Consideraciones adicionales
Gestión de errores: reintente errores transitorios, como los tiempos de espera de la red y los límites de tasa. No reintente con errores permanentes, como errores de autenticación o de entrada inválida. Configure estrategias de reintentos con el máximo de intentos y las tasas de retroceso adecuadas. Para ver ejemplos detallados, consulte Gestión de errores y reintentos.
Rendimiento: minimice el tamaño de los puntos de control; para ello, almacene las referencias en lugar de las cargas útiles completas. Utilice context.parallel() y context.map() para ejecutar operaciones independientes de forma simultánea. Operaciones relacionadas con lotes para reducir la sobrecarga de los puntos de control.
Control de versiones: invoque funciones con alias o números de versión para fijar las ejecuciones a versiones de código específicas. Asegúrese de que las nuevas versiones del código puedan gestionar el estado de las versiones anteriores. No cambie el nombre de los pasos ni su comportamiento de forma que interfiera con la reproducción.
Serialización: utilice tipos compatibles con JSON para las entradas y los resultados de las operaciones. Convierta las fechas en cadenas ISO y los objetos personalizados en objetos simples antes de pasarlos a operaciones duraderas.
Supervisión: habilite el registro estructurado con los identificadores de ejecución y los nombres de los pasos. Configuración de las alarmas de CloudWatch para conocer las tasas de error y la duración de la ejecución. Uso de la trazabilidad para identificar cuellos de botella. Para obtener una guía detallada, consulte Supervisión y depuración.
Pruebas: pruebe el flujo ideal, la gestión de errores y el comportamiento de reproducción. Pruebe los escenarios de tiempo de espera para detectar devoluciones de llamada y esperas. Utilice pruebas locales para reducir el tiempo de iteración. Para obtener una guía detallada, consulte Prueba de funciones duraderas.
Errores comunes que debe evitar: no anide las llamadas de context.step(); en cambio, utilice contextos secundarios. Encapsule las operaciones no deterministas en pasos. Establezca siempre tiempos de espera para las devoluciones de llamada. Equilibre la granularidad de los pasos con la sobrecarga de los puntos de control. Guarde referencias en lugar de objetos grandes en su estado.
Recursos adicionales
Documentación del SDK para Python
: referencia completa de la API, patrones de prueba y ejemplos avanzados Documentación del SDK para TypeScript
: referencia completa de la API, patrones de prueba y ejemplos avanzados