Implemente el patrón saga sin servidor mediante AWS Step Functions - Recomendaciones de AWS

Las traducciones son generadas a través de traducción automática. En caso de conflicto entre la traducción y la version original de inglés, prevalecerá la version en inglés.

Implemente el patrón saga sin servidor mediante AWS Step Functions

Creado por Tabby Ward (AWS), Rohan Mehta () y Rimpy Tewani () AWS AWS

Entorno: PoC o piloto

Tecnologías: Modernización; sin servidor

Carga de trabajo: código abierto

AWSservicios: Amazon API Gateway; Amazon DynamoDB; LambdaAWS; Amazon; Step Functions SNS AWS

Resumen

En una arquitectura de microservicios, el objetivo principal es crear componentes disociados e independientes para promover la agilidad, la flexibilidad y reducir el tiempo de comercialización de sus aplicaciones. Como resultado del desacoplamiento, cada componente del microservicio tiene su propia capa de persistencia de datos. En una arquitectura distribuida, las transacciones comerciales pueden abarcar varios microservicios. Como estos microservicios no pueden utilizar una sola transacción de atomicidad, coherencia, aislamiento y durabilidad (ACID), es posible que acabe con transacciones parciales. En este caso, se necesita alguna lógica de control para deshacer las transacciones que ya se han procesado. El patrón saga distribuido se utiliza normalmente para este propósito. 

El patrón saga es un patrón de gestión de fallos que ayuda a establecer la coherencia en las aplicaciones distribuidas y coordina las transacciones entre varios microservicios para mantener la coherencia de los datos. Si se utiliza el patrón «saga», cada servicio que realiza una transacción publica un evento que desencadena que los servicios subsiguientes realicen la siguiente transacción de la cadena. Esto continúa hasta que se complete la última transacción de la cadena. Si una transacción comercial fracasa, Saga organiza una serie de transacciones compensatorias que anulan los cambios introducidos en las transacciones anteriores.

Este patrón demuestra cómo automatizar la configuración y el despliegue de una aplicación de ejemplo (que gestiona las reservas de viajes) con tecnologías sin servidor, como AWS Step Functions, AWS Lambda y Amazon DynamoDB. La aplicación de ejemplo también utiliza Amazon API Gateway y Amazon Simple Notification Service (AmazonSNS) para implementar un coordinador de ejecución de saga. El patrón se puede implementar con un marco de infraestructura como código (IaC), como el AWS Cloud Development Kit (AWSCDK), el AWS Serverless Application Model (AWSSAM) o Terraform.

Para obtener más información sobre el patrón saga y otros patrones de persistencia de datos, consulte la guía Habilitar la persistencia de datos en los microservicios en el sitio web de Prescriptive Guidance. AWS

Requisitos previos y limitaciones

Requisitos previos 

  • Una cuenta de AWS activa.

  • Permisos para crear una AWS CloudFormation pila. Para obtener más información, consulte Controlar el acceso en la CloudFormation documentación.

  • El marco iAC de su elección (AWSCDKAWSSAM, o Terraform) se configuró con su AWS cuenta para que pueda usar el marco CLI para implementar la aplicación.

  • NodejS, utilizado para compilar la aplicación y ejecutarla localmente.

  • Un editor de código de su elección (como Visual Studio Code, Sublime o Atom).

Versiones de producto

Limitaciones

El abastecimiento de eventos es una forma natural de implementar el patrón de orquestación de la saga en una arquitectura de microservicios en la que todos los componentes están acoplados de forma flexible y no se conocen directamente entre sí. Si su transacción incluye un número reducido de pasos (de tres a cinco), el patrón saga podría ser una buena opción. Sin embargo, la complejidad aumenta con el número de microservicios y el número de pasos. 

Las pruebas y la depuración pueden resultar difíciles cuando se utiliza este diseño, ya que es necesario tener todos los servicios en ejecución para poder simular el patrón de transacciones.

Arquitectura

Arquitectura de destino

La arquitectura propuesta utiliza AWS Step Functions para crear un patrón de saga para reservar vuelos, reservar alquileres de coches y procesar los pagos de unas vacaciones.

El siguiente diagrama de flujo de trabajo ilustra el flujo típico del sistema de reservas de viajes. El flujo de trabajo consiste en reservar un viaje en avión («ReserveFlight»), reservar un coche («ReserveCarRental»), procesar los pagos («ProcessPayment»), confirmar las reservas de vuelos («ConfirmFlight») y confirmar el alquiler de un vehículo («ConfirmCarRental»), seguido de una notificación de confirmación cuando se hayan completado estos pasos. Sin embargo, si el sistema detecta algún error al ejecuter alguna de estas transacciones, empezará a fallar hacia atrás. Por ejemplo, un error en el procesamiento del pago («ProcessPayment») desencadena un reembolso («RefundPayment»), que luego desencadena la cancelación del coche de alquiler y del vuelo («CancelRentalReservation» y «CancelFlightReservation»), lo que finaliza toda la transacción con un mensaje de error.

Este patrón implementa funciones Lambda independientes para cada tarea que se resalta en el diagrama, así como tres tablas de DynamoDB para vuelos, alquileres de vehículos y pagos. Cada función de Lambda crea, actualiza o elimina las filas de las tablas de DynamoDB respectivas, en función de si la transacción se confirma o se revierte. El patrón usa Amazon SNS para enviar mensajes de texto (SMS) a los suscriptores, notificándoles las transacciones fallidas o exitosas. 

Flujo de trabajo para un sistema de reservas de viajes basado en el patrón de las sagas.

Automatizar y escalar

Puede crear la configuración de esta arquitectura mediante uno de los marcos de IaC. Utilice uno de los siguientes enlaces para su iAC preferido.

Herramientas

AWSservicios

  • AWSStep Functions es un servicio de organización sin servidor que le permite combinar funciones de AWS Lambda y otros AWS servicios para crear aplicaciones críticas para la empresa. A través de la consola gráfica Step Functions, puede ver el flujo de trabajo de su aplicación como una serie de pasos basados en eventos.

  • Amazon DynamoDB es un servicio SQL sin base de datos totalmente gestionado que proporciona un rendimiento rápido y predecible con una escalabilidad perfecta. Puede utilizar DynamoDB para crear una tabla de base de datos capaz de almacenar y recuperar cualquier cantidad de datos, así como de atender cualquier nivel de tráfico de solicitudes.

  • AWSLambda es un servicio informático que permite ejecutar código sin aprovisionar ni administrar servidores. Lambda ejecuta su código solo cuando es necesario y escala de manera automática, desde unas pocas solicitudes por día hasta miles por segundo.

  • Amazon API Gateway es un AWS servicio para crear, publicar, mantener, supervisar y proteger REST WebSocket APIs a cualquier escala. HTTP

  • Amazon Simple Notification Service (AmazonSNS) es un servicio gestionado que proporciona la entrega de mensajes de los editores a los suscriptores.

  • AWSCloud Development Kit (AWSCDK) es un marco de desarrollo de software para definir los recursos de las aplicaciones en la nube mediante lenguajes de programación conocidos TypeScript, como Python JavaScript, Java y C#/.Net.

  • AWSEl modelo de aplicaciones sin servidor (AWSSAM) es un marco de código abierto para crear aplicaciones sin servidor. Proporciona una sintaxis abreviada para expresar funciones, bases de datos y mapeos de APIs fuentes de eventos.

Código

El código de una aplicación de ejemplo que muestra el patrón saga, incluida la plantilla IaC (AWSCDK, o Terraform) AWSSAM, las funciones de Lambda y las tablas de DynamoDB, se encuentra en los siguientes enlaces. Siga las instrucciones de la primera epic para instalarlos.

Epics

TareaDescripciónHabilidades requeridas

Instale los NPM paquetes.

Cree un nuevo directorio, navegue hasta ese directorio en una terminal y clone el GitHub repositorio que prefiera en la sección de código que aparece anteriormente en este patrón.

En la carpeta raíz que contiene el package.json archivo, ejecute el siguiente comando para descargar e instalar todos los paquetes de Node Package Manager (NPM):

npm install
Desarrollador, arquitecto de la nube

Compilar scripts.

En la carpeta raíz, ejecuta el siguiente comando para indicar al TypeScript transpilador que cree todos los archivos necesarios: JavaScript

npm run build
Desarrollador, arquitecto de la nube

Esté atento a los cambios y vuelva a compilar.

En la carpeta raíz, ejecute el siguiente comando en una ventana de terminal independiente para comprobar si hay cambios en el código y compílalo cuando lo detecte:

npm run watch
Desarrollador, arquitecto de la nube

Ejecute pruebas unitarias (únicamente) AWSCDK.

Si utilizas el AWSCDK, en la carpeta raíz, ejecuta el siguiente comando para realizar las pruebas unitarias de Jest:

npm run test
Desarrollador, arquitecto de la nube
TareaDescripciónHabilidades requeridas

Implemente la pila de demostración enAWS.

Importante: La aplicación es independiente de la AWS región. Si utiliza un perfil, debe declarar la región de forma explícita en el perfil de la interfaz de línea de AWS comandos (AWSCLI) o mediante AWS CLI variables de entorno.

En la carpeta raíz, ejecute el siguiente comando para crear un ensamblaje de despliegue e implementarlo en la AWS cuenta y la región predeterminadas.

AWS CDK:

cdk bootstrap cdk deploy

AWS SAM:

sam build sam deploy --guided

Terraform:

terraform init terraform apply

Este paso puede tardar varios minutos en completarse. Este comando usa las credenciales predeterminadas que se configuraron para AWSCLI.

Observe la API puerta de enlace URL que se muestra en la consola una vez completada la implementación. Necesitará esta información para probar el flujo de ejecución de la saga.

Desarrollador, arquitecto de la nube

Compare la pila implementada con el estado actual.

En la carpeta raíz, ejecute el siguiente comando para comparar la pila implementada con el estado actual después de realizar cambios en el código fuente:

AWS CDK:

cdk diff

AWS SAM:

sam deploy

Terraform:

terraform plan
Desarrollador, arquitecto de la nube
TareaDescripciónHabilidades requeridas

Probar el flujo de ejecución de la saga.

Navegue hasta la API puerta de enlace URL que indicó en el paso anterior, cuando implementó la pila. Esto URL activa el arranque de la máquina de estados. Para obtener más información sobre cómo manipular el flujo de la máquina de estados mediante el paso de diferentes URL parámetros, consulte la sección de información adicional.

Para ver los resultados, inicie sesión en la consola AWS de administración y vaya a la consola Step Functions. Aquí puede ver todos los pasos de la saga State Machine. También puede ver la tabla de DynamoDB para ver los registros insertados, actualizados o eliminados. Si actualiza la pantalla con frecuencia, puede ver cómo el estado de la transacción cambia de apending. confirmed 

Puede suscribirse al SNS tema actualizando el código del stateMachine.ts archivo con su número de teléfono móvil para recibir SMS mensajes cuando las reservas se hayan realizado correctamente o no. Para obtener más información, consulta Amazon SNS en la sección Información adicional.

Desarrollador, arquitecto de la nube
TareaDescripciónHabilidades requeridas

Limpiar recursos.

Para limpiar los recursos desplegados para esta aplicación, puede usar uno de los siguientes comandos.

AWS CDK:

cdk destroy

AWS SAM:

sam delete

Terraform:

terraform destroy
Desarrollador de aplicaciones, arquitecto de la nube

Recursos relacionados

Documentos técnicos

AWSdocumentación de servicio

Tutoriales

Información adicional

Código

Con fines de prueba, este patrón implementa API Gateway y una función Lambda de prueba que activa la máquina de estados Step Functions. Con Step Functions, puedes controlar la funcionalidad del sistema de reservas de viajes pasando un run_type parámetro para imitar los errores en «ReserveFlightReserveCarRental,» «ProcessPayment,» «ConfirmFlight,» y «»ConfirmCarRental.

La función saga Lambda (sagaLambda.ts) toma la entrada de los parámetros de consulta del API GatewayURL, crea el siguiente JSON objeto y lo pasa a Step Functions para su ejecución:

let input = { "trip_id": tripID, // value taken from query parameter, default is AWS request ID "depart_city": "Detroit", "depart_time": "2021-07-07T06:00:00.000Z", "arrive_city": "Frankfurt", "arrive_time": "2021-07-09T08:00:00.000Z", "rental": "BMW", "rental_from": "2021-07-09T00:00:00.000Z", "rental_to": "2021-07-17T00:00:00.000Z", "run_type": runType // value taken from query parameter, default is "success" };

Puede experimentar con diferentes flujos de la máquina de estados Step Functions pasando los siguientes URL parámetros:

  • Ejecución correcta: https://{api gateway url}

  • Error al reservar el vuelo ─ https://{api gateway url}? runType= failFlightsReservation

  • Confirma el error del vuelo ─ https://{api gateway url}? runType= failFlightsConfirmation

  • Error al alquilar un coche de reserva ─ https://{api gateway url}? runType= failCarRental Reserva

  • Confirme que el alquiler del vehículo ha fallado ─ https://{api gateway url}? runType= failCarRental Confirmación

  • Error al procesar el pago ─ https://{api gateway url}? runType= failPayment

  • ¿Pasar un identificador de viaje ─ https://{api gateway url}? tripID= {de forma predeterminada, el ID del viaje será el ID de la AWS solicitud}

Plantillas iAC

Los repositorios enlazados incluyen plantillas de IaC que puede utilizar para crear toda la aplicación de reserva de viajes de muestra.

Tablas de DynamoDB

Estos son los modelos de datos para las tablas de vuelos, alquileres de coches y pagos.

Flight Data Model: var params = { TableName: process.env.TABLE_NAME, Item: { 'pk' : {S: event.trip_id}, 'sk' : {S: flightReservationID}, 'trip_id' : {S: event.trip_id}, 'id': {S: flightReservationID}, 'depart_city' : {S: event.depart_city}, 'depart_time': {S: event.depart_time}, 'arrive_city': {S: event.arrive_city}, 'arrive_time': {S: event.arrive_time}, 'transaction_status': {S: 'pending'} } }; Car Rental Data Model: var params = { TableName: process.env.TABLE_NAME, Item: { 'pk' : {S: event.trip_id}, 'sk' : {S: carRentalReservationID}, 'trip_id' : {S: event.trip_id}, 'id': {S: carRentalReservationID}, 'rental': {S: event.rental}, 'rental_from': {S: event.rental_from}, 'rental_to': {S: event.rental_to}, 'transaction_status': {S: 'pending'} } }; Payment Data Model: var params = { TableName: process.env.TABLE_NAME, Item: { 'pk' : {S: event.trip_id}, 'sk' : {S: paymentID}, 'trip_id' : {S: event.trip_id}, 'id': {S: paymentID}, 'amount': {S: "750.00"}, // hard coded for simplicity as implementing any monetary transaction functionality is beyond the scope of this pattern 'currency': {S: "USD"}, 'transaction_status': {S: "confirmed"} } };

Funciones de Lambda

Se crearán las siguientes funciones para respaldar el flujo y la ejecución de la máquina de estados en Step Functions:

  • Reservar vuelos: introduzca un registro en la tabla de vuelos de DynamoDB con transaction_status un pending de para reservar un vuelo.

  • Confirmar vuelo: actualiza el registro de la tabla de vuelos de DynamoDB para establecer transaction_status en confirmed, para confirmar el vuelo.

  • Cancelar reserva de vuelos: elimina el registro de la tabla de vuelos de DynamoDB para cancelar el vuelo pendiente.

  • Reserve vehículos de alquiler: inserta un registro en la tabla de CarRentals DynamoDB con transaction_status un pending de para reservar un alquiler de vehículos.

  • Confirmar alquileres de vehículos: actualiza el registro de la tabla de CarRentals DynamoDB para transaction_status confirmed establecerlo en y confirmar el alquiler de vehículos.

  • Cancelar reserva de vehículos de alquiler: elimina el registro de la tabla de CarRentals DynamoDB para cancelar el alquiler de vehículos pendiente.

  • Procesar pago: inserta un registro en la tabla de pagos de DynamoDB para el pago.

  • Cancelar pago: elimina el registro del pago de la tabla de pagos de DynamoDB.

Amazon SNS

La aplicación de ejemplo crea el tema y la suscripción siguientes para enviar SMS mensajes y notificar al cliente si las reservas se han realizado o no se han realizado correctamente. Si desea recibir mensajes de texto mientras prueba la aplicación de ejemplo, actualice la SMS suscripción con su número de teléfono válido en el archivo de definición de la máquina estatal.

AWSCDKfragmento (añada el número de teléfono en la segunda línea del siguiente código):

const topic = new sns.Topic(this, 'Topic'); topic.addSubscription(new subscriptions.SmsSubscription('+11111111111')); const snsNotificationFailure = new tasks.SnsPublish(this ,'SendingSMSFailure', { topic:topic, integrationPattern: sfn.IntegrationPattern.REQUEST_RESPONSE, message: sfn.TaskInput.fromText('Your Travel Reservation Failed'), }); const snsNotificationSuccess = new tasks.SnsPublish(this ,'SendingSMSSuccess', { topic:topic, integrationPattern: sfn.IntegrationPattern.REQUEST_RESPONSE, message: sfn.TaskInput.fromText('Your Travel Reservation is Successful'), });

AWSSAMfragmento (reemplaza las +1111111111 cadenas por tu número de teléfono válido):

StateMachineTopic11111111111: Type: 'AWS::SNS::Subscription' Properties: Protocol: sms TopicArn: Ref: StateMachineTopic Endpoint: '+11111111111' Metadata: 'aws:sam:path': SamServerlessSagaStack/StateMachine/Topic/+11111111111/Resource

Fragmento de Terraform (sustituya la cadena +111111111 por su número de teléfono válido):

resource "aws_sns_topic_subscription" "sms-target" { topic_arn = aws_sns_topic.topic.arn protocol = "sms" endpoint = "+11111111111" }

Reservas realizadas satisfactoriamente

El siguiente flujo ilustra una reserva correcta con «ReserveFlight,» «ReserveCarRental,» y «ProcessPayment» seguidos de «ConfirmFlight» y «ConfirmCarRental». Se notifica al cliente que la reserva se ha realizado correctamente mediante SMS mensajes que se envían al suscriptor del SNS tema.

Ejemplo de una reserva exitosa implementada por Step Functions mediante el patrón saga.

Reservas fallidas

Este flujo es un ejemplo de fracaso en el patrón de la saga. Si, después de reservar vuelos y alquileres de vehículos, «ProcessPayment» falla, los pasos se cancelan en orden inverso.  Se liberan las reservas y se notifica al cliente del fallo mediante SMS mensajes que se envían al suscriptor del SNS tema.

Ejemplo de una reserva fallida implementada por Step Functions mediante el patrón saga.