Architecture Microservice décentralisée

Antoine Detante
InTech / Innovation & Development
6 min readOct 3, 2017

L’année 2017 marquera l’entrée des technologies blockchain dans les systèmes d’information des entreprises. Au delà de démos & prototypes, de nouveaux services sont en train de voir le jour, basés sur le potentiel que représente ces architectures décentralisées. Mais en franchissant la porte des data-centers des grandes organisations, ces technologies initialement pensées pour fonctionner sur un réseau ouvert tel que Bitcoin, se sont transformées et adaptées aux contraintes des systèmes informatiques internes des entreprises.

Dans le cadre de la réalisation du projet FundsDLT (une plateforme décentralisée permettant d’optimiser le traitement des ordres dans l’industrie des fonds d’investissement), nous avons été amenés à faire cohabiter deux types d’architectures complémentaires :

  • Une architecture basée sur des micro-services, permettant une séparation des responsabilités en différents services au sein d’une même entité : service de validation des transactions, service listant les dernières transactions exécutées, …
  • L’utilisation d’une technologie blockchain basée sur Ethereum et ses Smart Contracts pour les échanges entre ces différentes entités (échanges d’informations entre les banques, les fournisseurs de KYC, les gestionnaires d’actif, …).

Cet article va présenter une généralisation de ce qui a été mis en place dans le cadre de FundsDLT, pour l’étendre à un système de communication décentralisé entre micro-services.

Event sourcing

Le coeur de la plateforme FundsDLT est développé en Scala, en utilisant le framework Lagom, qui permet de mettre rapidement en place une architecture micro-services en orientant certains des choix technologiques. Concernant la persistence des données, l’utilisation des patterns Event Sourcing et CQRS est encouragée.

Pattern Event Sourcing pour la modélisation d’une entité

Le pattern Event Sourcing vise à représenter l’état actuel de l’application comme la suite de tous les événements survenus sur le système. Concrètement, c’est cette liste d’événements qui va être stockée, à la différence de modèle relationnels classiques dans lesquels le stockage correspond à un instantané : l’état de l’application à un instant t.

Dans un modèle Event Sourcing, pour connaître l’état actuel de l’application il va être nécessaire de parcourir cette liste d’événements, dans l’ordre dans lequel ils sont survenus sur le système, en calculant à chaque étape le nouvel état.

Ce type de représentation permet de faciliter l’audit et l’analyse de l’application : il est ainsi aisé de restaurer un état précédent, de déterminer par quel enchaînement d’événements l’application s’est retrouvée dans un état donné, …

Ce pattern est également très adapté pour les applications dites “réactives” : immuabilité des événements (un événement passé ne peut être modifié, pour annuler son effet il faut ajouter un nouvel événement à la suite), asynchronisme pour faciliter la scalabilité du système (chaque commande envoyée à une entité est exécutée de façon asynchrone, qui va à son tour générer un ou plusieurs événements qui vont être stockés de façon asynchrone, …). Nous verrons par la suite que ces spécificités sont semblables aux caractéristiques des technologies blockchain, ce qui nous a incité à faire évoluer les fonctionnalités de Lagom en intégrant un stockage de ces événements de façon décentralisée.

Persistent Entities dans Lagom

L’Event Sourcing est implémenté dans Lagom au travers de Akka. Chaque PersistentEntity est une classe Scala, décrivant le comportement de l’entité, c’est à dire les événements produits (et persistés) pour chaque commande que va recevoir l’entité, et les changements d’états provoqués pour chacun de ces événements.

Lagom va ensuite démarrer un acteur Akka pour chaque instance de l’entité. Ces différents acteurs vont être distribués dans l’ActorSystem, sur un ou plusieurs noeuds en fonction de la définition du cluster.

Le stockage des événements repose sur la couche Akka Persistence, qui définit des interfaces standards pour lire et stocker des événements dans un système de stockage. Lagom utilise par défaut une implémentation persistant les données dans Cassandra, il existe d’autres implémentation pour Mongo, LevelDB et de nombreux backends de stockage.

Dans le cadre de ce projet, nous avons défini notre propre plugin de persistence (Journal dans la dénomination de Akka), utilisant un stockage décentralisé basé sur Tendermint.

Tendermint

Tendermint est un projet Open Source dont l’objectif est de généraliser les concepts des blockchains existantes, en séparant les problématiques intrinsèques à la technologie blockchain (réseau peer-to-peer, consensus distribué, création de blocks, diffusion des transactions, …) et l’application utilisant la blockchain.

Tendermint peut donc être vu comme un moteur de consensus décentralisé, ayant pour responsabilité la création des blocks de façon sécurisée et la diffusion de ces blocks parmi toutes les instances de Tendermint composant le réseau. Mais le format, le contenu, la validation et l’interprétation des données des transactions sont laissées libre à l’application.

Pour construire une architecture reposant sur Tendermint, il est nécessaire de déployer deux types de composants :

  • Les nœuds Tendermint (consensus engine) : composants développés par Tendermint, il s’agit d’un logiciel en Go qui va persister localement les données échangées sur la Blockchain, communiquer avec autres nœuds pour constituer le réseau p2p et communiquer avec l’application pour valider et distribuer les blocks créés
  • Une implémentation du protocole ABCI (Application BlockChain Interface), il s’agit d’une intégration à faire dans l’application pour traiter les requêtes TCP envoyées par Tendermint à l’application. L’application aura donc la responsabilité de valider les transactions (signature, format, …) avant inclusion dans un block par Tendermint, et de recevoir les blocks et transactions validées.

Le projet bénéficie aujourd’hui d’une popularité croissante parmi les technologies blockchain : Microsoft supporte notamment Tendermint dans son offre Azure « Blockchain-As-A-Service », Parity (un des principaux clients de la blockchain Ethereum) intègre Tendermint dans son API de « pluggable consensus », le projet est au cœur des plateformes Hyperledger’s Burrow et Cosmos, …

Intégration à Lagom

En implémentant un plugin pour Akka Persistence basé sur Tendermint, nous avons permis de répliquer l’état des PersistentEntities de Lagom sur différents clusters Akka en utilisant la blockchain comme couche de communication entre ces clusters.

Tendermint utilisé pour répliquer l’état des Entities Lagom

Pour chaque événement généré par l’entité, TendermintJournal créé une transaction et utilise l’API HTTP de Tendermint pour distribuer cette transaction à l’ensemble des noeuds qui composent cette blockchain.

Chaque instance du TendermintJournal doit dans un premier temps valider la transaction. Le format de la transaction est contrôlé, ainsi que sa signature qui doit correspondre à l’un des journaux autorisés à participer au consensus. La validité de l’événement est également contrôlé : on vérifie qu’il est cohérent avec l’état courant des différents journaux.

Si la transaction est validée, elle est inclue dans le prochain block par Tendermint et distribuée à l’ensemble des participants. L’implémentation d’ABCI sur chaque journal met alors à jour son stockage local, et l’état de l’entité est donc répliqué sur chaque cluster Lagom participant à cette blockchain.

Utilisation depuis les microservices

Du point de vue des services développés avec Lagom, cette intégration à la blockchain est transparente. Il suffit d’ajouter un trait particulier à l’application (TendermintPersistenceComponents) à la place de l’implémentation Cassandra standard. Ce trait va configurer le type de journal à utiliser pour le stockage.

Le développement des entités persistantes est ensuite réalisé avec l’API standard de Lagom (classe étendant PersistentEntity).

Le plugin Tendermint garantit alors que tous les événements transmis à ces entités seront reproduis sur les différents participants au réseau Tendermint.

Cas d’utilisation

Cette architecture permet d’adresser des applications pour lesquelles une partie du modèle de données doit être partagée par différents acteurs.

Il permet une synchronisation des états entre différents data-centers, sans utiliser de bus de message centralisé (tel qu’on aurait pu le mettre en place via des message brokers Kafka par exemple).

Dans le cas de la plateforme FundsDLT, ce modèle nous a permis de répliquer une partie de l’état de la plateforme (statuts des transactions d’achat/vente, statuts KYC des investisseurs, …) chez les différents acteurs participant à l’initiative.

--

--