Fuaaa, casi no llegué a la segunda semana de posteo.
Es este segundo post vamos a ver los siguientes temas:
- Que es ASL?
- Tipos de State
- Manejo de Errores
- Serverless
¿Qué es ASL?
Cuando hablamos de ASL en AWS hacemos referencia al Amazon States Language
.
Es un lenguaje estructurado basado en el formato JSON que se utiliza para definir las máquinas de estado, las cuales, a fin de cuentas, son una colección de Tasks. Estas Tasks pueden realizar una tarea (Task state), determinar a qué estados se debe pasar a continuación (Choice state), detener una ejecución con un error (Fail state), entre otros.
State Machines en ASL
Un ejemplo de una state machine orquestada en asl sería el siguiente:
{
"Comment": "A Hello World example demonstrating various state types of the Amazon States Language",
"StartAt": "Pass",
"States": {
"Pass": {
"Comment": "A Pass state passes its input to its output, without performing work. Pass states are useful when constructing and debugging state machines.",
"Type": "Pass",
"Next": "Hello World example?"
},
"Hello World example?": {
"Comment": "A Choice state adds branching logic to a state machine. Choice rules can implement 16 different comparison operators, and can be combined using And, Or, and Not",
"Type": "Choice",
"Choices": [
{
"Variable": "$.IsHelloWorldExample",
"BooleanEquals": true,
"Next": "Yes"
},
{
"Variable": "$.IsHelloWorldExample",
"BooleanEquals": false,
"Next": "No"
}
],
"Default": "Yes"
},
"Yes": {
"Type": "Pass",
"Next": "Hello World"
},
"No": {
"Type": "Fail",
"Cause": "Not Hello World"
},
"Hello World": {
"Type": "Pass",
"End": true
}
}
}
En las estructuras de las state machine contamos con los siguientes campos:
- Comment (Opcional) : Es en donde escribimos la descripción, ya sea de la tarea o de la máquina de estado.
- StartAt (Obligatorio): Indica el nombre en formato string que coincide exactamente con la tarea que inicia la máquina de estado (es
Case Sensitive
) - TimeoutSeconds (Opcional): Indica la cantidad máxima de segundos que puede durar la ejecución de la máquina.
- States (Obligatorio): Contiene el set de tareas que componen la máquina de estado.
Tipos de States
A la hora de trabajar con máquinas de estado, tenemos un total de 8 tipos de States que nos van a ayudar a la hora de la orquestación.
Task
Un State de tipo Task representa una única unidad de trabajo realizada por una máquina de estado.
Una Task realiza el trabajo mediante una actividad o una función de AWS Lambda, o pasando parámetros para consumir APIs de otros servicios.
"ActivityState": {
"Type": "Task",
"Resource": "arn:aws:states:us-east-1:123456789012:activity:HelloWorld",
"Next": "NextState"
}
Los campos campos obligatorios son;
- Type: En este caso estamos hablando del tipo Task.
- Resource: Un ARN que identifica de forma inequívoca la tarea específica que se va a ejecutar.
- Next o End: El campo next indica cual es la tarea que se va a correr una vez que se termina de ejecutar la tarea actual. Si queremos que el flujo finalice en esta tarea vamos a reemplazarlo por un
“End” : true
Pass
Este state toma la información del input y la entrega como output sin hacer ningún trabajo o actividad.
Es decir, , solo pass la información.
Bueno, ahora en serio...
Este es un ejemplo de un State de tipo Pass.
"No-op": {
"Type": "Pass",
"Result": {
"x-datum": 0.381018,
"y-datum": 622.2269926397355
},
"ResultPath": "$.coords",
"Next": "End"
}
En este tipo de state los campos obligatorios son Type y Next o End.
Lo opcionales son
- Result : Es la data que se pasa a la siguiente tarea, y en caso de tener un
ResulthPath
, es la posición que toma dentro del resultado. - ResultPath: Especifica dónde (en la entrada) se coloca la "salida" de la tarea virtual especificada en Result.
Es decir, si la entrada es
{
"georefOf": "Home"
}
La salida combinando el Result
con el ResulthPath
es
{
"georefOf": "Home",
"coords": {
"x-datum": 0.381018,
"y-datum": 622.2269926397355
}
}
Wait
Este state espera hasta el tiempo asignado y luego continúa con la task siguiente
"wait_ten_seconds": {
"Type": "Wait",
"Seconds": 10,
"Next": "NextState"
}
El tiempo asignado pueden ser segundos, declarándose en el campo Seconds
, o puede ser un tiempo absoluto declarando la fecha en el campo Timestamp
.
"Timestamp": "2016-03-14T01:59:00Z"
Choice
Es la que agrega la lógica de ramificación a la máquina de estado.
"ChoiceState": {
"Type": "Choice",
"Choices": [
{
"Variable": "$.name",
"StringEquals": "Blancanieves",
"Next": "Eat Apple"
}
],
"Default": "Not Eat Apple"
}
Los campos obligatorios son Type y Choices.
En Choices
van las distintas ramificaciones que puede tener la máquina de estado.
Existen distintos tipos de operadores de comparación, sus nombres son bastantes descriptivos.
- And
- BooleanEquals,BooleanEqualsPath
- IsBoolean
- IsNull
- IsNumeric
- IsPresent
- IsString
- IsTimestamp
- Not
- NumericEquals,NumericEqualsPath
- NumericGreaterThan,NumericGreaterThanPath
- NumericGreaterThanEquals,NumericGreaterThanEqualsPath
- NumericLessThan,NumericLessThanPath
- NumericLessThanEquals,NumericLessThanEqualsPath
- Or
- StringEquals,StringEqualsPath
- StringGreaterThan,StringGreaterThanPath
- StringGreaterThanEquals,StringGreaterThanEqualsPath
- StringLessThan,StringLessThanPath
- StringLessThanEquals,StringLessThanEqualsPath
- StringMatches
- TimestampEquals,TimestampEqualsPath
- TimestampGreaterThan,TimestampGreaterThanPath
- TimestampGreaterThanEquals,TimestampGreaterThanEqualsPath
- TimestampLessThan,TimestampLessThanPath
- TimestampLessThanEquals,TimestampLessThanEqualsPath
Es recomendable que la Task Choice tenga un campo llamado Default
para que en caso de que no coincida con ninguna choice pueda continuar el flujo.
Parallel
El state de tipo Parallel te permite ejecutar tareas de manera paralela.
{
"LookupCustomerInfo": {
"Type": "Parallel",
"End": true,
"Branches": [
{
"StartAt": "LookupAddress",
"States": {
"LookupAddress": {
"Type": "Task",
"Resource": "arn:aws:lambda:us-east-1:123456789012:function:AddressFinder",
"End": true
}
}
},
{
"StartAt": "LookupPhone",
"States": {
"LookupPhone": {
"Type": "Task",
"Resource": "arn:aws:lambda:us-east-1:123456789012:function:PhoneFinder",
"End": true
}
}
}
]
}
}
Los campos obligatorios son el Type, Next o End y Branches.
El campo Branches
son los flujos que se van a ejecutar de manera paralela, y siguen la sintaxis de una máquina de estado.
Succeed
Es la task utilizada para terminar las ejecución de manera exitosa. Es un tipo de state que no necesita un campo Next o End.
"SuccessState": {
"Type": "Succeed"
}
Fail
Termina la ejecución con de la máquina de estado con una ejecución fallida.
Este state tampoco necesita de un campo Next o End.
"FailState": {
"Type": "Fail",
"Cause": "Invalid response.",
"Error": "ErrorA"
}
Los campos Cause
y Error
son opcionales.
Map
Es el state que permite ejecutar varios pasos para cada iteración de un elemento.
Es decir, mientras que el Parallel
ejecuta distintos flujos al mismo tiempo, el Map
ejecuta el mismo flujo para distintos elementos.
"Validate-All": {
"Type": "Map",
"Iterator": {
"StartAt": "Validate",
"States": {
"Validate": {
"Type": "Task",
"Resource": "arn:aws:lambda:us-east-1:123456789012:function:ship-val",
"End": true
}
}
},
"End": true
}
Los campos obligatorios son Type e Iterator
, en este campo se define la máquina de estado que va a procesar la data.
Manejo de errores
Para el manejo de errores tenemos dos campos que podemos utilizar dentro de las states.
Retry : se va a encargar de la cantidad de reintentos de un state en caso de que falle. Solo está permitido en los states de tipo
Task
yParallel
.Catch: Se encarga de atrapar el error y redireccionarlo al flujo al que corresponde. Solo está permitido en los states de tipo
Task
,Map
yParallel
.
Ejemplo
Suponiendo que tenemos un state de tipo Task, necesitamos que
- Si falla la ejecución, deben hacerse 3 intentos.
- Cuando falla la tercera ejecución, queremos manejar el error para enviarlo a un flujo en particular.
"ValidateCreditCard": {
"Type": "Task",
"Resource": "arn:aws:states:us-east-1:123456789012:function:Validate",
"Retry": [
{
"ErrorEquals": [
"States.ALL"
],
"MaxAttempts": 3
}
],
"Catch": [
{
"ErrorEquals": [
"Error"
],
"Next": "Format Error Response",
}
],
"Next": "NextState"
}
Para los reintentos tenemos el campo Retry
, y dentro de este tenemos otros dos campos importantes.
- ErrorEquals: va a ser la condición para los reintentos, es decir, solo cuando el error coincida con el mencionado, vamos a tener un reintento.
- MaxAttemps: es la cantidad de reintentos para nuestra ejecución.
"Retry": [
{
"ErrorEquals": [
"States.ALL"
],
"MaxAttempts": 3
}
]
Para el manejo de error vamos a usar el campo Catch
, y este lleva los siguientes campos.
- ErrorEquals: va a ser el error que queremos atrapar
- Next es el nombre del próximo step si coincide con el error.
"Catch": [
{
"ErrorEquals": [
"Error"
],
"Next": "Format Error Response",
}
],
Tanto el campo Catch
como el Retry
son arreglos de objetos, lo que permite el manejo de distintos tipos de errores.
Serverless
¿Qué es serverless
? Es un modelo de ejecución, en el cual un proveedor de la nube (AWS, Google, o Azure) es responsable de ejecutar un fragmento de código mediante la asignación dinámica de los recursos. Y solo cobrando por la cantidad de recursos utilizados para ejecutar el código.
A la hora de trabajar con este modelo podemos recurrir a distintos frameworks. Uno de ellos es SAM
(Serverless Application Model), el cual es un framework de código abierto creado para las arquitecturas serverless. Es el framework de AWS.
El framework que vamos a estar utilizando para crear nuestras máquinas de estados en esta serie va a ser Serverless Framework
, el cual es un framework también de código abierto que fue el primero en ser creado para este tipo de arquitectura y es el más usado.
El modelo serverless
también suele ser conocido como FaaS
(Function as a Service).
Para su instalación necesitamos...
1 - Tener NodeJs instalado. (Instalar NodeJs https://nodejs.org/en/)
2 - Correr este comando en la consola (Docu instalación : https://www.serverless.com/framework/docs/getting-started)
npm install -g serverless
Recomiendo tener esto instalado para el cuarto capítulo.
Fin
Este ha sido otro capítulo con material teórico.
En el próxima vamos a estar viendo un par de servicios de AWS que vamos a necesitar conocer para poder pasar luego a la creación de las máquinas de estado.
Para esto voy a necesitar que creen una cuenta en AWS, si es que no la tienen.
Si el contenido les sirvió, no olviden que pueden invitarme un cafecito.
Nos vemos la próxima semana.