Le modèle Acteur
A l’échelle atomique ou unitaire d’Akka existent des acteurs. Ils représentent un paradigme de programmation différent de celui utilisé dans le développement traditionnel. La majorité des projets implémentent des concepts de programmation orientés objet ou fonctionnel. Des applicatifs y sont souvent développés de manière séquentielle en utilisant des threads.
L’acteur modèle apporte un souffle nouveau à ce monde. Un acteur n’est ni plus ni moins qu’une classe, qui peut être implémentée en Java ou en Scala. La différence vient des méthodes accessibles seulement depuis l’acteur. Les méthodes des acteurs ne sont pas appelées directement depuis l’acteur.
Le seul moyen de communiquer avec un acteur est de lui envoyer un message à travers le système d’acteur proposé par Akka.
Avec le système d’acteurs d’Akka, les messages sont envoyés de manière asynchrone entre les différents acteurs. Comme schématisé sur la figure ci-dessus, les messages sont d’abord transmis dans la mailbox (boîte aux lettres) des acteurs. Cette mailbox sert de tampon et permet à l’acteur de traiter les messages dans l’ordre d’arrivée (FIFO). Ceci couvre les mécanismes de base du modèle acteur. Akka permet de construire un système d’acteurs, communiquant entre eux en s’échangeant des messages.
Les messages des cycles d’acteurs Akka
Voici comment cela fonctionne. Sur la figure ci-dessus est illustré un exemple où l’acteur A envoie un message à l’acteur B. Une analogie peut être effectuée entre cet envoi de message asynchrone et l’envoi de SMS entre deux personnes. A transmet un message à B. B reçoit le message et A est libre de passer à d’autres tâches. A n’est pas bloqué dans l’attente de recevoir une réponse de B comme cela se produit en utilisant les méthodes de programmation orientée objet “classiques”. Dans ce cas, A est libre de passer à un nouveau traitement si besoin, ou de libérer des ressources.
Dans la figure ci-dessus, l’acteur B reçoit le message de A qui induit un changement d’état. Par exemple, dans le cas où B représente un compte bancaire, et où le message envoyé par A est “un crédit de 100 euros est effectué sur ce compte” alors l’état de la balance du compte dans B doit changer. On parle d’un changement d’état de l’acteur B. Il est alors possible à B (de manière optionnelle) de répondre à l’acteur A en lui disant que l’action a bien été effectuée.
Un environnement multiple
En réalité, A et B peuvent exister dans un environnement distribué sur plusieurs machines. Cela nous pousse à nous poser la question dès le début de la gestion des cas de déconnexion entre les différentes machines. Que se passe-t-il si A ne peut pas répondre à B ?
La figure ci-dessus montre comment A peut s’adresser directement à l’Actor System avec une requête du type : “Je voudrais que tu planifies un message à me renvoyer dans une certaine durée dans le futur”. Cela peut être de l’ordre de la milliseconde, la seconde ou encore de la minute. Dans tous les cas, une stratégie sera mise en place pour que, dans le cas où B ne peut pas répondre à A, un message de timeout soit renvoyé à A.
Dans la figure ci-dessus, A reçoit ce message de timeout, qui est un des deux types de messages que l’acteur A sait interpréter dans cet exemple : une réponse de B ou un message de timeout. A sait comment réagir dans chacun de ces deux cas. Ce comportement est différent des exceptions levées dans les langages de programmation traditionnels où une exception peut entraîner une réaction en chaîne et faire tomber tout un système. Dans le paradigme d’Akka et de l’Actor modèle, la résilience joue un rôle incontournable dans l’architecture du système d’information et a été intégré dans la conception d’origine du modèle acteur.
La Supervision des Acteurs Akka
La supervision des acteurs complète le mécanisme de résilience précédemment évoqué. Comme schématisé sur la figure 6, les acteurs sont capables de créer de nouveaux acteurs, formant une hiérarchie d’acteurs. Dans cet exemple, l’acteur A crée de multiple Acteurs “workers” notés W. L’acteur A et les acteurs W sont liés par une relation parent/ enfant ( resp. acteur A/acteur W).
La relation entre l’acteur parent et l’acteur enfant est une relation de supervision. Lorsque l’un des acteurs enfants rencontre un problème, par exemple une exception, il remonte la problématique en question. L’acteur superviseur définit un comportement à adopter pour gérer cette erreur. Cette stratégie de supervision est implémentée au sein d’Akka et peut être enrichie selon le besoin de l’utilisateur en terme de supervision.
Lorsqu’il reçoit une exception de la part de l’acteur supervisé (W), le superviseur (A) peut adopter une des réactions suivantes :
- L’exception levée n’est pas dangereuse. L’acteur A demande à W de continuer sans s’en préoccuper,
- L’exception levée nécessite de relancer l’acteur W. A demande à W de se relancer,
- L’exception nécessite d’arrêter l’acteur W,
- L’exception se complique et aucune stratégie ne permet de résoudre le problème. L’acteur A remonte l’exception levée à son propre superviseur.
Cette hiérarchie permet d’escalader les problèmes jusqu’à trouver le bon interlocuteur (acteur) pouvant répondre au problème. Ce modèle de résolution des problèmes est une force du modèle acteur et est mis à disposition du développeur pour augmenter la résilience de son code.
Les développeurs qui débutent avec l’acteur modèle ont tendance à concentrer beaucoup de codes métier au sein d’un même acteur. Mais au fur et à mesure des développements, il devient de plus en plus naturel de subdiviser en unités logiques propres aux acteurs (diviser pour mieux régner).
Self Healing
Une des raisons principales pour “diviser et régner” est de réduire les risques d’occurrence des problèmes. Le modèle acteur est conçu pour déléguer les opérations les plus risquées aux acteurs les plus bas dans la hiérarchie, donc les plus supervisés. Par exemple, dans la figure 7 on dispose des utilisateurs (acteurs) A1, B1 et C3 avec C3 délégant des opérations à risque aux acteurs D. Pour l’exemple, nous nous concentrons sur un des acteurs D, l’acteur D3.
Les acteurs en bout de chaîne sont schématisés en rouge pour signifier qu’ils effectuent des opérations à risque. Comme par exemple les opérations en base de données ou la lecture de fichiers sur le filesystem. Ces opérations sont risquées car dépendantes d’autres facteurs comme le réseau, l’état de santé de la base de données ou l’existence du fichier sur le filesystem qui sont des variables inconnues à l’exécution.
En repoussant ces opérations risquées aux acteurs enfants (D3), les acteurs superviseurs (C3, B1 et A1) sont protégés par un “bouclier” de défense. Avec la hiérarchie d’acteur, le travail est délégué de manière à produire un système à granularité de spécialisation fine. Celui-ci permettant de maîtriser les comportements à risque des acteurs en bas de la hiérarchie.
Routing et Concurrence
Akka est spécialisé dans les systèmes multi-threads, concurrentiels sur plusieurs cores. Il permet de simplifier les opérations traditionnellement réalisées avec plusieurs threads manuellement définis. Contrairement à la définition manuelle des threads engendrant de nombreuses problématiques de concurrence, Akka met à disposition un système concurrentiel éliminant ou simplifiant de nombreux challenges de la programmation concurrentielle et multi-thread en Scala et Java.
La figure ci-dessus donne un exemple de la gestion concurrentielle des événements (ou autres types de message). A et B schématisent deux acteurs parents. Un acteur “routeur” R et un nombre défini d’acteurs “worker” W effectuant une tâche donnée. Sur le schéma, l’acteur A envoie un message au Routeur. Celui-ci délègue l’action à un acteur worker sans analyser le message reçu.
Pendant que cet acteur Worker réalise la tâche demandée par A, l’acteur B envoie un message au routeur lui demandant de réaliser une certaine tâche. Le routeur envoie ce message vers un worker disponible pour réaliser l’action. Au même moment le Worker ayant effectué l’action demandée par A renvoie une réponse à celui-ci. Nous avons un exemple de gestion concurrentielle multi-threads sans aucune configuration manuelle. Depuis le point de vue de A et B, c’est l’acteur R (routeur) qui réalise tout le travail demandé. En réalité, R a délégué toutes ses tâches aux acteurs W sans que cela soit perçu par A et B.
Sur la Figure ci-dessus, on distingue un autre aspect intéressant de la stratégie de supervision d’Akka : l’acteur A envoie un message au routeur R, qui le délègue à un worker W. Ce worker rencontre un problème et lève une exception.
Les mécanismes
Dans la programmation classique, nous utiliserons un try catch classique et l’exception serait normalement renvoyée à A. Cependant, avec le modèle acteur, c’est le superviseur (R) qui voit l’exception. Celui-ci peut remonter à A un message disant “Je n’ai pas pu effectuer la tâche demandée, que veux-tu que je fasse ?”, et A n’a pas à implémenter une gestion d’exception qui n’est pas dans son coeur de métier.
Il existe aussi un mécanisme de timeout lors d’envoi de message (pattern ask) permettant de dire: “si je ne reçois pas de message avant une certaine durée, j’adopte le comportement X”. Dans tous les cas, A ne voit pas l’exception et son code non pollué par un comportement qui n’est pas le sien.
Avec le modèle acteur dans le coeur d’Akka, de nombreux outils permettent de gérer toute la concurrence et d’augmenter la résilience de l’applicatif dans sa globalité. Cet outil augmente la productivité du développeur et sécurise les systèmes distribués où il est appliqué.
Les acteurs Akka et leurs cycles en résumé
Les éléments clés à retenir de cette section concernant le modèle acteurs Akka :
- Les acteurs sont des unités “stateful”, avec un état donné, communiquant via le passage de messages asynchrones,
- Les acteurs sont légers (~3kb par acteur) et ne bloquent pas les threads. Contrairement aux systèmes traditionnels, souvent synchrones et bloquants,
- Enfin, Les acteurs peuvent créer de nouveaux acteurs et utiliser les stratégies de supervision natives d’Akka pour augmenter la résilience face aux problèmes rencontrés.
Spécialiste de sujets liés aux Architecture Reactives, j’ai travaillé sur de nombreux projets stratégiques de refonte SI impliquant plusieurs métiers. Je suis également passionné par les sujets liés à l’Agile, je contribue d’ailleurs au blog Organisation Performante.
N’hésitez pas à me faire un retour sur cet article ou à me contacter sur LinkedIn pour partager nos actualités!
Nidhal
Laisser un commentaire