Aller au contenu principal
Retour au blogue

Développement logiciel

AWS step functions: un aperçu

Phu Lam Nguyen
02 févr. 2022 ∙ 10 mins
Ordinateur entrouvert avec le clavier éclairé par la lumière de l'écran

AWS a initialement publié les « step functions » à la fin de 2016. Bien que ce service soit disponible depuis cinq ans, il ne fait pas beaucoup parler de lui sur le Web. Même après avoir parcouru d'innombrables articles « Top x des services AWS les plus couramment utilisés », vous auriez du mal à trouver une seule mention des step functions ou des didacticiels de base sur la façon de les configurer au-delà de la documentation officielle d'AWS. Les informations concernant les step functions sont difficiles à trouver. Dans cet article, je vais vous guider à travers les bénéfices de ce service, son utilisation générale et ses potentiels avantages.

Présentation

Pour faire simple, les step functions AWS nous permettent de créer visuellement des workflow qui suivent un ensemble d'étapes prédéfinies pour atteindre un objectif spécifique à la fin de leurs exécutions avec Workflow Studio, ou via un schéma que nous lui fournissons. Ce schéma est écrit en Amazon States Language (ASL), un langage structuré basé sur JSON utilisé pour définir votre machine d'état.

Les step functions gèrent automatiquement les échecs et les tentatives, ce qui peut représenter un investissement en temps important. Cela permet aux équipes de développement de concentrer leurs efforts sur d’autres priorités et sur logique d’affaires.

Les step functions peuvent aussi exécuter des tâches sur de nombreux services AWS, mais par souci de concision, cet article se concentrera principalement sur leur interopérabilité avec Lambdas.

Comment ça marche?

Les step functions débutent en lisant le schéma écrit en ASL qui leur est fourni.

Chaque état (étape) nécessite un nom unique dans les diagrammes de machine à état et les états sont référencés par leur nom. Ces états sont essentiellement des étapes que la machine va parcourir, chacune d'entre elles représentant une tâche qu'elle doit accomplir.

Le schéma aura les 3 propriétés suivantes à sa racine :

  • Commentaire : String - Une description rapide de la machine d'état et de ses utilisations
  • StartAt : String - Le point de départ avec la valeur représentant le nom du premier état
  • States : Array - Une liste de tous les états dans la machine

En général, la plupart des états auront au moins les deux propriétés suivantes : Type et Next. Le premier est une chaîne représentant le type de travail effectué sur la machine d'état tandis que le second pointe vers l'état suivant une fois que l'exécution en cours est terminée.

Le Type doit être l'une des valeurs prédéfinies d'AWS :

  • Task - Exécute une tâche pour effectuer un certain travail, généralement utilisée pour exécuter une fonction Lambda
  • Choice - Branching paths, on en sélectionne un en fonction de la condition fournie
  • Wait - Attendre pour un spécifique laps de temps ou jusqu'à une certaine date
  • Parallel - Exécute plusieurs chemins de branchement en même temps
  • Map - Exécute un ensemble d'étapes pour chaque élément dans un tableau d'entrée fourni
  • Pass - Ne fait rien, prend l'entrée et l'envoie comme sortie, utile pour le débuggage
  • Succeed /Fail - Termine l'exécution, ne nécessite pas de propriété Next comme les autres états

Lorsque la machine d'état est lancée, elle exécute d'abord l'état nommé dans la propriété StartAt. Une fois que c’est fait, elle examinera la propriété Next et progressera dans l'arborescence jusqu'à ce qu'elle atteigne un état avec la propriété "End": true ou un état avec "Type": "Succeed", "Type": "Fail".

Notez que lorsque vous essayez de créer une nouvelle step function sur la console AWS, vous aurez la possibilité de choisir entre des workflows standard (par défaut) ou express. Le premier est principalement utilisé pour les tâches qui peuvent prendre une longue période de temps, tandis que le second est principalement utilisé pour les tâches fréquentes, à volume élevé.

Quels sont les avantages de l'utilisation des step functions ?

L'utilisation des step functions présente de nombreux avantages, en voici quelques-uns que nous voudrions souligner :

  • Facilite grandement l'orchestration de plusieurs fonctions Lambda et services pour effectuer une tâche spécifique.
  • Permet aux développeurs de se concentrer davantage sur la logique d’affaires pendant que la machine d'état gère l'orchestration et la gestion des erreurs du workflow.
  • Cette séparation permettra également aux fonctions Lambda d'être plus réutilisables car elles seront moins fortement couplées et pourront être utilisées indépendamment.
  • Le graphique visuel généré par le schéma des step functions permettra aux développeurs d'expliquer facilement les concepts et les workflows aux utilisateurs non techniques.
  • Intégration native avec d'autres services AWS et mise à l'échelle automatique en fonction de l'évolution des charges de travail.
  • (Workflows standard uniquement) Fournit des journaux d'exécution détaillant chaque état lors de l’exécution d'une machine d'état pour un débogage plus facile (journaux d'entrée/sortie complets).
  • La gestion des erreurs peut être effectuée dans la machine d'état plutôt que dans la fonction Lambda, mais une combinaison des deux est idéale.

Quelques mises en garde

Voici quelques inconvénients à prendre en compte :

  • Coûts supplémentaires - vous pouvez vous attendre à payer 1 $ pour 40 000 transitions d'état, en plus des coûts de service supplémentaires avec lesquels le service step function interagit.
  • Les charges utiles de la step functions ont une limite de seulement 256 Ko, la manipulation de fichiers n'est pas recommandée (il serait préférable d'utiliser une URL S3 présignée).
  • Verrouillage du fournisseur. Amazon States Language est unique à AWS et puisque les step functions gèrent toute la coordination entre les services AWS (Lambdas), passer d'AWS à un autre fournisseur sera plus difficile car vous devrez réécrire toute l'orchestration effectuée par AWS.
  • Les types d'état de choix ne prennent en charge que les conditions de base telles que les comparaisons de nombres, qu'une variable soit présente ou non ou qu'une chaîne soit égale à quelque chose.
    Les conditions plus complexes ne sont pas prises en charge, une solution consisterait à ajouter une étape Lambda pour calculer la condition et inclure le résultat dans la réponse Lambda. La machine d'état peut alors l'utiliser comme condition et la supprimer au début de l'état suivant.
  • (Workflow standard uniquement) Les workflows standard sont utilisés pour les tâches à long terme et sont asynchrones. Lorsqu'une step function standard est exécutée, nous obtenons uniquement l'exécution ARN et l'horodatage du début de l'exécution au lieu d'une réponse.
  • (Workflow express uniquement) Les workflows express ne disposent pas des journaux d'exécution détaillés présents avec les workflow standard, le débogage des workflows express peut donc rapidement devenir un vrai cauchemar.

Performances et évolutivité

Comme pour tout autre service, vous souhaitez connaître ses performances et son évolution en fonction de l'évolution de la charge de travail avant de l'utiliser dans un environnement PROD. Vous serez heureux de savoir qu'il y a peu ou pas d'impacts négatifs sur le temps d'exécution lorsqu'une step function est appelée à partir d'un API. Aussi, les step functions évoluent automatiquement et vous n'aurez pas à vous en soucier.

Voici un exemple concret, disons que nous avons une application pour envoyer des messages aux utilisateurs connectés, les messages doivent être enregistrés et filtrés avant d'être envoyés.

Nous allons exécuter la machine d'état à partir d'un point de terminaison sur une passerelle API.

Step functions

La step function elle-même est relativement simple, mais implique une poignée d'autres services tels que la lecture/écriture DynamoDB, l'accès au compartiment S3, les appels Lambda et la propagation des messages du Web socket. Notez qu'il utilise le workflow Express.

Tout d'abord, il transmettra la charge utile à un Lambda dans le message reçu qui gère la réorganisation des données dans un format plus facile à lire. Il exécutera ensuite deux Lambdas en parallèle : Enregistrer le message dans la base de données et Filtrer le message.

La tâche de Save Message consisterait à enregistrer le message dans DynamoDB, tandis que Filter Message récupérerait un fichier de S3 à utiliser comme liste noire pour filtrer le contenu du message. Après avoir traversé le filtre, Propagate Message gérera l'envoi du message à chaque client Websocket actuellement connecté. Message Sentest simplement un état de "Type": "Pass"avec End défini sur true pour marquer la fin de la machine d'état.

Maintenant, regardons le graphique d'exécution du test de charge K6 ci-dessous :

exécution du test de charge K6

Nous avons soumis le point de terminaison à un test de charge de 12 minutes composé de 50 utilisateurs, en commençant par 10 utilisateurs et en allant jusqu'à 50, comme on le voit à partir de la ligne violette. Comme vous pouvez le voir tout au long du test, le temps d'exécution ne change jamais de façon spectaculaire à l'exception de la première exécution, qui est due au démarrage à froid de Lambda.

Voici un aperçu plus détaillé des temps d'exécution

temps d'exécution

Malgré la step function impliquant plusieurs services différents et des opérations asynchrones, le temps d'exécution moyen n'était que de 176 millisecondes avec 95 % de ces 16 631 requêtes prenant moins de 313 ms.

Pour vérifier l'intégrité des résultats, nous avons effectué le même test 5 fois et déterminé un écart de seulement 5 à 15 ms.

Maintenant, tout cela ne veut pas dire qu'une step function est un outil d'orchestration gratuit sans inconvénient en termes de performances. Chaque fois qu'une transition d'état a lieu, la machine d'état déclenche des activités avant et après l'exécution et bien que le coût de performance ne soit pas élevé du tout, c'est toujours quelque chose à garder à l'esprit, en particulier avec les machines d'état qui seront fréquemment exécutées. Voir ci-dessous :

activités avant et après l'exécution

Il s'agit du journal d'exécution d'une machine à états très simple (à 2 états). Le premier état exécute un lambda qui renvoie simplement une chaîne et l'état suivant est de type Pass qui marque la fin de l'exécution.

Vous remarquerez qu'il y a un délai de 75 ms entre le début de l'exécution de la machine d'état et la planification de l'exécution de Lambda, avec 19 ms supplémentaires jusqu'à l'exécution réelle de Lambda. Ensuite, vous remarquerez qu'il y a un délai de 21 ms entre la fin de l'exécution de Lambda et la planification de l'état suivant (étapes 6 à 7).

Coûts

Avant d'évoquer les chiffres, il faut savoir que les workflows Standard et Express sont facturés différemment.

Les workflow standard sont facturés par transition d'état, c'est-à-dire chaque fois que la machine d'état passe d'un état à un autre. Les 4 000 premières transitions d'état sont gratuites, mais les transitions suivantes coûteront 0,000025 USD chacune, soit 0,25 USD pour 10 000.

Les workflows express, quant à eux, sont facturés en fonction du nombre de requêtes et de la durée. Chaque workflow coûtera 0,000001 $ par demande, soit 1 $ pour 1 million de demandes.

La durée de chaque demande express s'ajoute également au prix et suit ces règles :

  • 0,00001667 $ par Go-seconde (0,0600 $ par Go-heure) pour les 1 000 premières heures Go-heures
  • 0,00000833 $ par Go-seconde (0,0300 $ par Go-heure) pour la prochaine 4 000 heures Go-heures
  • 0,00000456 $ par Go-seconde (0,01642 $ par Go-heure) au-delà

Vous pouvez trouver le guide de tarification complet sur le site Web d'AWS.

Ces chiffres ne semblent pas si pires sur papier, mais ils s'accumulent rapidement lorsque vous avez un vaste bassin d'utilisateurs. Prenons le scénario suivant comme exemple :

  • Vous avez une application avec 10 000 utilisateurs quotidiens
  • La fonctionnalité principale de votre application utilise une step function de workflow standard
  • La machine d'état a 7 transitions d'état au total qu'elle doit traverser
  • Un utilisateur, en moyenne, exécutera cet état machine 12 fois par jour

Sachant cela, l'application vous coûtera 0,0021$ par jour par utilisateur, 21$ par jour pour une base d'utilisateurs de 10 000 ou 7665$ par an pour une base d'utilisateurs de 10 000. Ce prix ne tient même pas compte de tous les d'autres services avec lesquels votre machine d'état communiquera.

D'autres facteurs peuvent augmenter le prix à l'avenir, comme le fait d'avoir une base d'utilisateurs croissante ou une augmentation des transitions d'état par machine d'état pour ajouter des fonctionnalités.

Conclusion

Bien que les step functions ne soient pas quelque chose que vous ajouterez à chaque nouvelle application que vous développez, en particulier compte tenu du coût supplémentaire, cela vaut la peine de considérer si vous avez un cas où son utilisation est appropriée.

Par exemple, avec les workflow standard, vous pouvez l'utiliser pour gérer les cas où un administrateur doit approuver l'action d'un utilisateur avant de pouvoir continuer, ce qui est susceptible de prendre plus de temps que la limite de 15 minutes d'un Lambda contrairement à un workflow standard. La machine d'état peut être arrêtée jusqu'à ce que l'approbation soit donnée, après quoi elle reprendra et enverra une notification à l'utilisateur. Tout cela est géré par la machine d'état afin que vous n'ayez pas à ajouter un champ « statut » dans votre base de données.

Il est préférable de les réserver aux types de workflows suivants :

  • Logique critique pour l'entreprise (telle que la gestion des paiements)
  • Complexe : un workflow qui devrait orchestrer de nombreux services dispersés
  • Potentiellement très long : certains services peuvent prendre beaucoup de temps à processus, également exemple ci-dessus
  • Nécessitant potentiellement une interaction humaine à un moment donné (exemple ci-dessus)

Les step functions ne doivent être implémentées que si vous avez un cas d'utilisation approprié ou si votre application peut bénéficier de ses fonctionnalités. Les raisons énoncées ci-dessus sont un bon moyen de déterminer si tel serait le cas pour votre projet.

Envie d'en savoir plus sur le sujet, accédez au guide de développement complet de l'équipe AWS, et si vous avez des questions ou des commentaires sur cet article, contactez-nous!

Crédit photo: Philipp Katzenberger