Data Management et Azure Service Fabric

Hello !

Suite à ce précédent article je vais aujourd’hui parler gestion des donnés avec des microservices dans Azure Service Fabric.

Cet article est une “réponse” aux questions soulevées ici !

Gestion des données

Il est bien sur possible d’utiliser des bases de données existantes (on prem) et d’héberger tout type de base de données dans Azure si besoin pour répondre aux différentes problématiques Data de vos applicatifs.

  • SQL Server
  • NoSQL : mongoDB
  • MySql

En ce qui concerne la séparation des données par service ASF, il n’y a pas de solutions meilleures qu’une autre. Chaque microservice est responsable de ces données et de leurs cohérences mais il n’y a pas d’obligation de provisionner une base de données pour chaque service. Nos options sont :

  • Chaque service à son jeu de tables attribués et ne peut effectuer des opérations CRUD que sur ces tables. Un seul microservice doit avoir accès à une table de la base de données. Il est donc interdit à un service B de réaliser une opération CRUD sur les données dont est responsable le service A.

4 - Data Management et Azure Service Fabric

  • Un service pour un schéma de la base.
  • Un service : une base de données.
  • Découpage lecture/écriture des données avec la mise en oeuvre du pattern CQRS.

L’architecte positionnera en fonction des contraintes et besoins de chaque solution la meilleure gestion de donnée pour le système d’informations.

Gestion des transactions

Les microservices peuvent-ils partager une transaction ?

Si une opération de mon SI nécessite deux microservices, comment font-ils pour se partager la transaction et garantir la cohérence du système en cas d’erreur ? Il faudrait pouvoir faire un rollback en cas d’échec et un commit en cas de succès mais sur les deux services via une même transaction.

Il s’agit d’une problématique purement logicielle à traiter manuellement avec éventuellement :

  • Commit en deux étapes : voir MSDN.
  • Méthode d’annulation : gestion par le développeur d’une méthode Non A pour chaque méthode A.

Ces deux façons de faire sont compliquées à mettre en œuvre et le risque d’erreur est important … Elles ne sont pas conseillées pour du microservice… Après tout si deux services sont impliqués dans une transaction commune, le découpage en « Bounded Context » de l’approche DDD n’est probablement pas optimal !

Ici nous avons traité de problématiques logicielles qui ne sont pas forcément spécifiques à Service Fabric mais à l’implémentation d’une architecture microservices en général. Il me semblais important d’en parler tout de même.

Communication et Azure Service Fabric

Hello !

Suite au dernier article je vais présenter comment Service Fabric peut nous aider à répondre à certaines problématiques liées à la mise en œuvre de microservices. Aujourd’hui l’aspect communication !

Cet article est une “réponse” aux questions soulevées ici !

Communication clients / services

 

Nous avons deux possibilités pour qu’un client (web, application Windows, mobile) puissent échanger avec un service :

  • Communication directe

1 3 - Communication et Azure Service Fabric

  • Ou en  utilisant un composant intermédiaire : un API Gateway

Nous pouvons alors développer notre propre API Gateway :

2 3 - Communication et Azure Service Fabric

Ou utiliser une passerelle de Type Azure API Management :

3 3 - Communication et Azure Service Fabric

Cet outil permet de configurer simplement un API Gateway dans Azure. Il n’y a pas de développement supplémentaire à produire.

APIM est conçue pour :

  • Gérer les API complexes avec des règles de routage
  • Un contrôle d’accès (Authentification)
  • Une surveillance
  • Une journalisation des événements
  • Une mise en cache des réponses

Attention en contrepartie notre point d’accès unique à notre API est par définition un point de défaillance important de notre système. S’il tombe, il n’y a plus de communication possible. Du côté du trafic réseaux il peut également devenir un goulot d’étranglement s’il ne s’adapte pas à la charge.

Communication entre services

 

Pour la communication entre services nous avions listé deux possibilités :

  • Echange synchrone via commande HTTP

Attention ici il s’agit bien de l’appel qui est synchrone dans le sens ou le contact entre les deux services est direct. Au niveau applicatif l’appel peut être asynchrone dans le sens ou le client peut faire un traitement en attendant une réponse du service.

Si la communication entre services est directe, cela implique que les services sachent à quelle adresse ils peuvent s’appeler. Pour cela, Azure Service Fabric nous propose une solution de Reverse Proxy.

Au démarrage d’un service celui-ci vient s’identifier auprès du service d’attribution de noms d’ASF. Celui-ci tient une table qui mappe les instances de service et les adresses de point de terminaison :

4 3 - Communication et Azure Service Fabric

La résolution et la connexion aux services impliquent l’exécution des étapes suivantes en boucle :

  • Obtenir le point de terminaison publié par un service à partir du Service d’attribution de noms.
  • Se connecter au service sur le point de terminaison en question.
  • Si la tentative de connexion échoue, les étapes précédentes de résolution et de connexion doivent être réessayées, et ce cycle se répète jusqu’à ce que la connexion aboutisse ou qu’elle soit désactivée (Pattern circuit breaker)

Appel entre services :

5 3 - Communication et Azure Service Fabric

Appel depuis l’extérieur :

6 3 - Communication et Azure Service Fabric

Dans les deux cas c’est le reverse proxy qui nous renseigne sur les url des instances de services accessibles.

  • Échange asynchrone via un bus d’évènement basé sur le protocole AMQP.

7 3 - Communication et Azure Service Fabric

Si nos besoins nous conduisent vers une communication asynchrone, nous pouvons utiliser Azure Service Bus. Il y a alors deux cas d’utilisation.

    • Les files d’attente

Elles permettent une communication unidirectionnelle. Chacune agit comme un intermédiaire (ou broker) qui stocke les messages envoyés jusqu’à leur réception. Chaque message est reçu par un destinataire unique.

Il s’agit du cas le plus simple pour une communication par message : un émetteur, une file d’attente, un destinataire.

8 2 - Communication et Azure Service Fabric

  • Les rubriques

Les expéditeurs envoient les messages à la rubrique de la même façon qu’ils envoient des messages dans la file d’attente. Ces messages ont le même aspect.

À l’inverse des files d’attente cependant, un message unique envoyé à une rubrique peut être reçu par plusieurs abonnements. Cette approche, communément appelée publication et abonnement (ou pub/sub), est utile quand plusieurs applications sont intéressées par les mêmes messages.

9 2 - Communication et Azure Service Fabric

Les files d’attente et les rubriques dans Azure Service Bus se basent sur le protocole AMQP : ce protocole de messagerie open standard permet le développement d’applications basées sur des messages à l’aide de composants créés avec plusieurs langages, infrastructures et systèmes d’exploitation.

10 2 - Communication et Azure Service Fabric

Qu’il s’agisse d’une communication synchrone via appel HTTP ou asynchrone avec Azure Service Bus, les deux implémentations sont possibles avec Azure Service Fabric. Les deux solutions ont des avantages et des inconvénients, à chacun de les mesurer en amont du projet !

Mon architecture microservices dans Azure

Maintenant que nous avons présenté les problématiques à étudier pour la mise en œuvre de microservices :

Ainsi que la façon dont gérer l’intégration et le déploiement continu dans VSTS, il est temps de s’intéresser aux moyens qu’Azure met à notre disposition pour héberger nos composants logiciels !

Azure est une plateforme Cloud d’hébergement d’applications, de données et de services créés en 2008 par Microsoft. Les solutions proposées par Azure sont nombreuses. Ils se déclinent en trois principales catégories :

1 3 - Mon architecture microservices dans Azure

L’IaaS (Infrastructure as a Service) est une externalisation de l’infrastructure informatique matérielle. L’offre gère pour nous :

  • L’installation des serveurs fichiers
  • Les réseaux
  • Le stockage de données

Le PaaS (Platform as a Service) est un IaaS plus poussé. Il consiste à sous-traiter non seulement l’infrastructure matérielle mais également vos applications middleware :

  • Systèmes d’exploitation
  • Base de données
  • Serveurs web

A nous ensuite d’y ajouter nos applications et services.

Le SaaS (Software as a Service) est la version la plus aboutie et la plus complète de l’externalisation de composants du système d’information. Le fournisseur gère, pour nous :

  • L’installation
  • La configuration
  • Le fonctionnement
  • La maintenance

2 3 - Mon architecture microservices dans Azure

Pour l’hébergement d’applications de type microservices dans Azure nous disposons de plusieurs possibilités avec des offre de type PAAS.

Web App

Les web applications constituent le moyen le plus simple d’héberger une application dans Azure. Il s’agit d’une solution PAAS qui fais partie du groupe de fonctionnalités Azure App Services.

3 - Mon architecture microservices dans Azure

Web App est un service pour l’hébergement d’applications web, d’API REST et de backends mobiles. Vous pouvez y déployer des applications développées en .NET, .NET Core, Java, Ruby, Node.js, PHP ou Python.Les Web App sont déployés sur des machines virtuelles Windows ou Linux.

Il est également possible d’y déployer des applications s’exécutant dans un conteneur Docker.

Azure Container Service

On passe à une solution PAAS bien plus complète que les « simples » WebApp.

ACS est une plateforme de conteneur pouvant être orchestré par :

4 5 - Mon architecture microservices dans Azure

  • DC/OS
  • Docker Swarm
  • Kubernetes  : (l’orchestrateur Docker de Google) : on parle alors d’AKS.

5 - Mon architecture microservices dans Azure

Azure Container Service est une solution permettant de déployer, provisionner et manager des conteneur Docker.

La technologie d’un conteneur virtualise le système d’exploitation par rapport aux applications. Par rapport aux machines virtuelles, les conteneurs présentent les avantages suivants :

  • Ils sont bien plus légers. Un conteneur ne contient que l’application à déployer et ces dépendances.
  • Démarrage rapide : comme les conteneurs n’ont pas besoin d’initialiser l’intégralité d’un système d’exploitation, ils peuvent démarrer beaucoup plus rapidement, généralement en quelques secondes.
  • Portabilité : une image d’application en conteneur peut être portée de manière à s’exécuter dans le cloud ou sur site, à l’intérieur de machines virtuelles ou directement sur des machines physiques.

L’utilisation de cette plateforme me semble intéressent pour un SI qui maitrise déjà docker et un orchestrateur et qui veux migrer vers le Cloud. Historiquement Docker et les orchestrateurs de conteneur adresse plutôt des technologies open source mais se sont tournés récemment vers Microsoft grâce à .Net Core.

La troisième option est le concurrent direct d’ACS / AKS.

Azure Service Fabric

6 2 - Mon architecture microservices dans Azure

Azure Service Fabric est la plateforme de microservices signée Microsoft. Elle peut être déployée OnPrem sur des serveurs Windows Server 2016 ou Linux, dans le Cloud sous Azure, mais également dans n’importe quel autre Cloud.

La plateforme est mise à disposition de tous depuis 2015 mais Microsoft l’éprouve depuis plusieurs années. En effet plusieurs services Azure utilisent cette infrastructure :

  • Skype pour les entreprises
  • DocumentDB
  • Event Hubs
  • Azure SQL Database (qui héberge plus de 1,4 million de bases de données clients)
  • Cortana qui peut traiter plus de 500 millions de requêtes par seconde.

Source MSDN : «  Azure Service Fabric est un orchestrateur de services sur un cluster de machines. Azure Service Fabric est une plateforme de systèmes distribués qui facilite le packaging, le déploiement et la gestion de conteneurs et de microservices évolutifs et fiables. Les développeurs et administrateurs sont en mesure d’éviter les problèmes d’infrastructure complexes et peuvent se concentrer sur l’implémentation de charges de travail stratégiques et exigeantes, évolutives, fiables et faciles à gérer. »

Autrement dit, il s’agit d’une plateforme PaaS associée à un système d’orchestration des services, façon Kubernetes.

7 2 - Mon architecture microservices dans Azure

Azure Service Fabric propose :

  • Une gestion de la haute disponibilité des services.
  • Un modèle de programmation simple.
  • Une scalabilité des services à grande échelle.
  • Un partitionnement des données.
  • Une gestion fine des mises à jour que ce soit en upgrade ou en downgrade.
  • Un monitoring simple de la santé de vos services.
  • Un démarrage et un arrêt rapide des services.
  • La gestion du load balancing des services.
  • Une gestion de récupération automatique des services.
  • Un système de réplication et de gestion de failover.

Les différents types d’applicatifs pouvant être exécutés dans Service Fabric sont :

  • Stateless service : Un service au sens courant qui ne maintiens pas d’état entre les appels.
  • Stateful service : Un service capable de conserver des informations grâce aux ReliableDictionary qui garantis une persistance des données entre les différentes instances du service.
  • Actor service : Par exemple, un panier d’un utilisateur sur un site de e-commerce peut être un actor service.
  • Guest exécutable : Permet d’exécuter une application exe dans Service Fabric
  • Container : Exécutions d’un conteneur docker dans ASF : disponible depuis peu.

Ces différents types de services peuvent être développé en utilisant .Net ou .Net Core.

Dans les prochains articles nous allons reprendre point par point les problématiques relevés pour l’implémentation d’une architecture microservices et détailler comment Azure Service Fabric réponds à chacun d’entre eux. Je reviendrais plus tard également sur Azure Container Services 🙂

Microservices et Application Lifecycle Management

Le but d’un microservice étant d’être isolé, facilement testable et déployable, un critère important de cette mise en œuvre est l’utilisation d’un outil de build et de déploiement continu (continuous intégration / continuous déploiement).

Des solutions existent sur le marché comme TeamCity ou Jenkins. Ici nous parlerons bien sur de Microsoft Visual Studio Team Services 🙂

VSTS  permet :

  • D’avoir une forge logicielle avec un outils de gestion de version.
  • De configurer des processus de build avec exécution de tests automatisés
  • De configurer des processus de releases : déploiement sur des serveurs ou dans le Cloud.

1 - Microservices et Application Lifecycle Management

Au-delà de l’aspect CI/CD VSTS permet également de gérer un projet en méthode agile avec la gestion des itérations de développement (sprints), les work items, backlog etc …

Une maturité DevOps est obligatoire pour la mise en œuvre de notre architecture. En effet, nos services seront nombreux et doivent pouvoir être déployé rapidement suite à une évolution. Sans une plateforme DevOps d’industrialisation logicielle pour nous aider, la tâche s’annonce plus que compliqué.

2 - Microservices et Application Lifecycle Management

Intégration

La partie intégration est assurée par :

  • Un outil de gestion de version : Git qui n’est plus à présenter ou TFVC, l’outils de gestion de version Microsoft, en fin de vie. La firme ne conseille plus son utilisation. A noter que VSTS peut également récupérer les sources d’un dépôt disant comme GitHub.
  • Un outil de Builds, intégré à VSTS.

3 1 - Microservices et Application Lifecycle Management

Les builds sont configurables, s’exécutent sur une branche du repository git et permettent de réaliser un certains nombre d’actions :

  • Télécharger les dépendances Nuget du projet.
  • Compiler la solution.
  • Exécuter les tests automatisés.
  • Exécuter des commandes Windows.
  • Pousser l’artifact généré .
  • Envoyer un rapport de build par mail.
  • Lancer un tests Sonar.
  • …..

De la façon la plus concise possible, sur un projet de type .Net core la build se déroulera en 4 commandes :

  • dotnet restore
  • dotnet build
  • dotnet tests
  • dotnet publish

Tests

Pour nos services, différent type de tests sont à mettre en œuvre pour garantir la stabilité du code source et éviter les régressions :

Tests unitaires

Chaque test valide le bon fonctionnement d’une méthode bien précise de notre service, l’utilisation d’un framework de mock (moq, rhinoMock) est indispensable pour garantir le caractère « unitaire » de nos tests. Un framework de mock permet de simuler le fonctionnement d’une méthode.

Par exemple, nous testons la méthode B. Dans l’implémentation de B il y a un appel a la méthode A qui retourne un booléen. Alors pour notre test de B on précisera en amont que notre méthode A renverra systématiquement true si elle est appelée. Pendant notre test si A() est appelé, on est assuré d’avoir le résultat true, et on peut tester notre méthode B indépendamment de A.

Microsoft propose son propre framework de mocking : Microsoft.Fakes.

A noter que la mise en œuvre d’une stratégie Test Driven Development (TDD) peut aider à garder une couverture de tests satisfaisante.

Tests d’intégration

Chaque test valide le bon fonctionnement d’une méthode de notre service, de l’appel jusque la base de données. Le test balaie donc la totalité de notre méthode. Par exemple avec l’appel GET http://www.urltest.com/clients/2,  on pourra valider qu’en sortie on obtient un client provenant de la base de données dont l’identifiant est 2.

Tests de qualité

Il est possible d’intégrer un outils comme Sonar pour la qualimétrie logicielle et l’analyse du code :

  • Respect des normes de développement
  • Complexité cyclomatique
  • Présence des commentaires
  • Duplication de code
  • Évaluation de la couverture de code

4 1 - Microservices et Application Lifecycle Management

Tests statiques

On peut utiliser le module de code review de VSTS pour la relecture de code entre développeurs.

Les tests statiques sont effectués par les développeurs avant de pousser leurs modifications sur la forge. Les tests unitaires, d’intégration et de qualité quand à eux pourront être exécuté de manière automatisée par notre outils DevOps pendant une build. En cas d’erreur sur un des tests, l’archivage sera rejeté pour être corriger par le développeur.

Déploiements

La partie Déploiements de notre solution est géré par les « Releases » de VSTS. Les releases permettent à partir d’une build de déployer nos dll dans un environnement cible, serveurs interne ou environnement cloud.

L’hébergement de notre architecture microservices peut se faire dans un environnement Cloud afin de répondre facilement aux besoins de disponibilités et de scalabilité des applications. Ici nous nous intéresserons évidemment à Azure et aux différentes solutions offertes par cette plateforme pour répondre à notre besoin.

Les releases permettent en plus du déploiement d’effectuer des opérations comme :

  • Jouer des scripts SQL
  • Déplacer des fichiers (xml, json)
  • Exécuter des commandes PowerShell, FTP

A noter que des outils externes à Microsoft s’interface très bien avec VSTS, au niveau des builds comme des releases pour exécuter diverses taches. Je pense notamment à Octopus, Sonar, Docker, WebPack … Un système de plugin est même mis en œuvre pour pouvoir ajouter des fonctionnalités à VSTS.

Microsoft VSTS est donc un outils très complet pour la gestion du cycle de vie de nos applications. Il conviendra parfaitement dans le cadre d’un projet microservices déployé dans Azure.

Problématiques pour la mise en oeuvre de microservices (part. 3)

Pour ce dernier article sur les problématiques à étudier avant la mise en œuvre de microservices nous traiterons de la gestion des erreurs dans nos services.

Gestion des logs et monitoring

Comment gérer la collecte de log et le monitoring dans un système éclaté, distribué et auto scalable ?

Le besoin de logs et de monitoring est un enjeu majeur, dans cet environnement encore plus qu’ailleurs. Nous avons besoins d’outils permettant de :

  • Récolter les logs applicatifs
  • Récolter les logs systèmes et réseaux
  • Les présenter de façon lisible et structurée
  • Récolter les métriques de performances systèmes et réseaux
  • Les présenter sous forme de graphique
  • Surveiller les métriques en temps réel.

Gestion des pannes et résilience

Comment garantir à nos clients une SLA optimale compte tenu du caractère fortement distribué de notre SI ?

Il ne faut pas perdre de vue que résistant à la panne ne veut pas dire infaillible. Quand un service tombe, il faut un mécanisme pour identifier cette panne et relancer le service en question.

Cette résilience des architectures microservices passe donc par :

  • Un mécanisme de surveillance.
  • Un démarrage et une configuration des serveurs automatisés.
  • Un déploiement des services automatisé.

Notre architecture mettant en œuvre un grand nombre de composants communiquant par HTTP le nombre d’erreurs est forcément plus important que dans un cadre d’exécution plus  classique et une communication inter processus.

Les besoins de notre système sont :

    • Détecter quand un service est off pour ne pas que le client tente de le joindre inutilement.
    • Auto guérison des services : le cloud favorise la gestion de ce besoin par la mise en œuvre de :
      • Scalabilité horizontale : duplication automatique des composants logiciels.
      • Scalabilité verticale : augmentation de la puissance de la plateforme hôte (CPU / RAM / espace disque).

Au niveau logiciel, on peut également agir en mettant en œuvre un pattern appelé circuit breaker. Il permet de contrôler la collaboration entre différents services afin d’offrir une grande tolérance à la latence et à l’échec. Pour cela, en fonction d’un certain nombre de critères (timeout, nombre d’erreurs, élément dans la réponse), ce pattern permet de désactiver l’envoi de requêtes au service appelé et de renvoyer plus rapidement une réponse alternative de repli (fallback), aussi appelé graceful degradation.

La gestion des erreurs dans ce type de système est tellement importante que Netflix à prévu un composant chargé de débrancher des services aléatoirement pour s’assurer de la résilience de son système : c’est le célèbre Chaos Monkey.

« Le but de cet outil est de simuler des pannes en environnement réel et de vérifier que le système informatique continue à fonctionner. »

On s’assure ainsi d’avoir anticipé correctement la survenue de ce type d’incidents en mettant en place une architecture suffisamment redondante pour qu’une panne de serveurs n’affecte d’aucune façon les millions d’utilisateurs de Netflix.

 

C’est la fin de cette série d’articles sur les problématiques à étudier avant de se lancer dans l’implémentation de microservices ! Nous avons parlé de :

Après cette introduction très théorique nous verrons comment nous pouvons répondre à toutes ces problématiques grâce aux différentes briques Azure 🙂

A très vite !

Problématiques pour la mise en oeuvre de microservices (part. 2)

Pour ce deuxième article sur les problématiques à étudier avant la mise en œuvre de microservices nous traiterons de la gestion des données.

Data Management

Les services partagent-ils la même source de données  ou faut-il privilégier l’approche un service = un datastore ?

3 - Problématiques pour la mise en oeuvre de microservices (part. 2)Figure 4-7. Comparaison de la souveraineté des données : base de données monolithique et microservices

Chaque microservice est responsable de ces données et de leurs cohérences. C’est une dépendance externe, et elle doit être adaptée en fonction des besoins :

  • Base de données relationnelle (Oracle, SQLServer)
  • NoSQL (MongoDB par exemple)

Toutefois, il est tout à fait acceptable que les services partagent le même serveur de base de données physique. Mais chaque service doit être le garant de ces données ! Le problème survient quand les services partagent le même schéma, ou lisent et écrivent sur le même jeu de tables de base de données.

4 - Problématiques pour la mise en oeuvre de microservices (part. 2)

Il n’y a pas d’obligation de provisionner une base de données pour chaque service. Avec un SGBDR nous avons plusieurs possibilitées :

  • Chaque service à son jeu de tables attribués et ne peut effectuer des opérations CRUD que sur ces tables. Un seul microservice doit avoir accès à une table de la base de données. Il est donc interdit à un service B de réaliser une opération CRUD sur les données dont est responsable le service A.
  • Un service pour un schéma de la base.
  • Un service : une base de données.

Puisqu’on évoque le principe de « separation of concern » au niveau entités, on peut aller plus loin encore dans cette démarche. Le CQRS (Command and Query Responsibility Segregation) est une architecture qui permet de séparer la lecture (Query) de l’écriture (Command).

Le pattern CQRS consiste à séparer le modèle d’écriture du ou des modèles de lecture. Cela répond à un constat simple : les applications ont des besoins différents en écriture et en lecture.

5 - Problématiques pour la mise en oeuvre de microservices (part. 2)

  • La lecture doit être performante. Elle permet d’accéder à des données agrégées et filtrées nécessitant une dénormalisation.
  • L’écriture nécessite des performances moindres car souvent moins importante en termes de volumétrie. Par contre, elle gère des règles métiers complexes et la cohérence entre les données.

Cette approche peux être intéressante si une opérations d’écriture nécessite des traitement couteux sur les données car elle permet de ne pas impacter les clients en lecture. Cette approche demande, en contrepartie, un effort d’architecture et de développement conséquent ! La encore, il faudra faire vos choix en fonction de vos besoins.

Gestion des transactions

Les microservices peuvent-ils partager une transaction ?

Si une opération de mon SI nécessite deux microservices, comment font-ils pour se partager la transaction et garantir la cohérence du système en cas d’erreur ? Il faudrait pouvoir faire un rollback en cas d’échec et un commit en cas de succès mais sur les deux services via une même transaction.

Cela ne posait pas de problème avec SOAP et WCF (voir le standart WS-AT). Ici, avec REST ce n’est tout simplement pas possible !

Il faut donc gérer ce problème de façon logiciel. Des patterns sont utilisables

Mais couteux à mettre en œuvre. Ce genre de pratique peux surtout être symptomatique d’un mauvais découpage fonctionnel !

La question qu’il faudrait plutôt se poser serait : Si deux microservices doivent partager / échanger des données, ne devraient-ils pas être fusionnés en un seul ?

Problématiques pour la mise en oeuvre de microservices (part. 1)

Pour réussir l’implémentation ou la migration vers une architecture microservices, un certain nombre de problématiques techniques sont à étudier en amont, en parallèle du découpage fonctionnel du SI.

Aujourd’hui nous traiterons de deux problématiques dans notre approche de mise en œuvre d’une architecture microservice :

  • Communication clients / services
  • Communication entre services

Communication clients / services

Le consommateur de mon service doit-il avoir un accès direct à celui-ci ou faut-il utiliser un composant de méditation intermédiaire comme un API Gateway ?

Un API Gateway est un composant logiciel qui expose nos services à un client. Ainsi le client n’a d’échange qu’avec la passerelle et pas directement avec nos services.

1 - Problématiques pour la mise en oeuvre de microservices (part. 1)

L’API Gateway peux même être découpé pour éventuellement adresser les clients différents.

On parle alors de modélisation « Backends for frontends ».

2 1 - Problématiques pour la mise en oeuvre de microservices (part. 1)

L’utilisation de la passerelle d’API offre les avantages suivants :

  • Il dissocie les clients des services. Les services peuvent être versionnés ou refactorisés sans avoir à mettre à jour tous les clients.
  • Les services peuvent utiliser des protocoles de messagerie qui ne sont pas compatibles avec le web, comme AMQP.
  • La passerelle d’API peut exécuter d’autres fonctions transverses, telles que l’authentification, la journalisation, la terminaison SSL et l’équilibrage de charge.
  • La passerelle peux se charger de la découverte et indexation des services

Attention, la passerelle ne contient pas de fonctionnel, il ne s’agit que d’un « passe plat ».

La communication entre services

Les microservices vont communiquer entre eux. Comment doivent-ils procéder ?

Question primordiale à mon sens, en effet la complexité des microservices n’est pas dans leurs code source, mais dans leurs échanges.

Il y a deux possibilités pour faire communiquer nos services :

  • Communication synchrone
  • Communication asynchrone

Il n’y a pas de solutions meilleure que l’autre et le bon procédé est celui qui correspond à nos besoins.

Effectuer des appels synchrones

Le service client envoie une requête à un second service, il attend pendant le traitement de la requête et il récupère la réponse du service en fin de traitement.

Les appels synchrones sont les plus simples à mettre en œuvre. Les services communiqueront par appels REST et s’échangeront les données dans le format de leur choix (XML / JSON / binaire).

Mais attention, nos microservices doivent être instanciable automatiquement pour répondre à une hausse de la charge par exemple. Compte tenu de leur « volatilité », comment se trouve-t-il sur le réseau s’ils ont besoin de communiquer ?

Nous avons ici définis un nouveau besoin de composant logiciel :

  • Auquel les microservices se déclarent lors de leur initialisation.
  • Qui enregistre les adresses de chaque microservices.
  • Qui route les appels vers le bon destinataire.

Ce composant se nomme “service de noms”.

Effectuer des appels asynchrones

Ces appels se font en utilisant un bus d’échange de message. Chaque service envoie des messages sur le bus qui seront consommés ensuite par d’autres services. L’émetteur publie sur le bus. Le ou les destinataires qui se sont abonnés à ce type d’évènements sur le bus sont notifié et peuvent alors récupérer des données.

L’émetteur de l’évènement n’a pas de connaissances des clients qui s’abonnent. Ce type d’appels permet de moins coupler les services entre eux. En effet chaque service n’a qu’un seul correspondant : le bus de messages.

Cette façon de communiquer entre applications nous rappelle les fameux ESB (Entreprise Service Bus) adopté massivement par les SI il y a quelques années. Ces composants vendus par des sociétés tierces ont souvent causé bien des problèmes aux DSI. Mais la ou les ESB étaient « intelligent » (transformation, orchestration, routage) un bus de service sert uniquement de canal de transport. Son seul rôle est de stocker l’information en attendant qu’un service tiers la récupère.

image22 - Problématiques pour la mise en oeuvre de microservices (part. 1)

La deuxième architecture avec le bus de messages à beaucoup d’avantages mais est plus lourde à mettre en œuvre.

Cette implémentation permet une plus grande flexibilité que les communications synchrones classiques :

  • Découplage entre les services : le client envoie sa requête sur un canal sans connaître le service qui va la traiter.
  • Message tampon : les messages sont placés dans des files d’attente et seront traités de façon asynchrone par le service même s’il n’est pas disponible au moment de l’envoi du message.
  • Communications interprocessus explicites : il n’y a pas de différences entre un appel à un service local ou à distance.
  • L’asynchronisme rend plus robuste et plus tolérant le système. Le bus permet de scaler horizontalement tout type de services simplement et efficacement.

Nous venons de traiter deux types d’architectures microservices. La première avec communication par service REST est certainement la plus simple à mettre en œuvre. Elle est efficace et rapide à implémenter lorsqu’il s’agit de migrer depuis une application monolithique. La seconde est plus lourde, mais également plus modulaire et tolérante aux pannes.

Il est par ailleurs tout à fait envisageable de mixer les deux types d’architecture afin d’obtenir une communication hybride. Ceci peut par exemple être envisagé lors d’une migration progressive vers du tout asynchrone.

Dans tous les cas, quel que soit le modèle choisis, il est fondamental de documenter, via des diagrammes de séquences par exemple, les dépendances entre service, car c’est ici que se situe la complexité de votre système d’informations !

Découpage microservices : Oui mais comment ?

Un microservice est avant tout une unité fonctionnelle. Il correspond à une fonctionnalité précise, logique et cohérente du système. Un microservice est donc autonome vis à vis de la fonctionnalité qu’il réalise. Il a son propre code, gère ses propres données et ne les partage pas, pas directement en tout cas, avec d’autres services. L’approche nécessite un effort de conception pour faire émerger des unités fonctionnelles autonomes.

Pour parvenir à un résultat cohérent au niveau du service en lui-même et au niveau global du SI (vision de l’urbaniste) plusieurs idées :

  • Séparer la complexité fonctionnelle et technique : le service répond à un besoin fonctionnel, pas applicatif !
  • Eviter le couplage entre services. S’il y en a trop le contexte est peux être mal délimité !
  • Trouver un équilibre entre macroservices et nanoservices.

Pour arriver à ce résultat,  nous pouvons utiliser l’approche Domain Driven Design d’Eric Evans qui a largement fait ces preuves. DDD, proposé par Evans dès 2003, est une manière de penser la conception autour du code, de collaborer et de communiquer (via un langage commun et clairement définis) avec les experts fonctionnels et d’avoir une implémentation centrée sur le métier. Le besoin de cohérence fonctionnelle très forte au niveau du découpage de microservices  se recoupe très bien avec l’approche DDD.

ddd 227x300 - Découpage microservices : Oui mais comment ?

Cette approche nous permettra de découper notre SI en domaine fonctionnel, en accord avec le métier et de ces domaines nous bâtirons nos différents microservices !

Pour une vision plus complète du sujet, consulter : https://cdiese.fr/domain-driven-design-en-5-min/ (il vous faudra plus que 5min pour lire cet article !) et docs.microsoft.com.

Quelles technologies .Net pour du Microservices ?

 téléchargement - Quelles technologies .Net pour du Microservices ?téléchargement - Quelles technologies .Net pour du Microservices ?Le choix du type de service : WCF vs Web API

WCF est un Framework  de communication de Microsoft. Une application WCF permet de bâtir et de faire communiquer des services basés sur le protocole SOAP. Il succède au service de type ASMX. Les services WCF permettent également de mettre en œuvre une architecture REST mais Microsoft propose depuis 2012 un nouveau type d’application : les Web API.

ASP.Net WebAPI est apparu avec ASP.Net MVC 4. C’est la solution proposée par Microsoft pour permettre aux développeurs de construire rapidement des services web REST. La principale différence entre WebAPI et MVC est que l’un possède des vues alors que l’autre retourne des données sérialisées (JSON/XML).

Avec l’avènement de .NET Core, Microsoft a fusionné les produits ASP.Net MVC et ASP.Net WebAPI. Les classes a manipuler pour développer des projets de type WEB API ou MVC sont maintenant les mêmes !

MSDN nous indique : « Utilisez WCF pour créer des services Web dignes de confiance et sécurisés accessibles via un large éventail de transports. Utilisez l’API Web ASP.NET pour créer des services HTTP qui sont accessibles à partir d’une large gamme de clients.

Utilisez l’API Web ASP.NET si vous créez et concevez de nouveaux services REST. Bien que WCF prenne en charge l’écriture de services REST, la prise en charge de REST dans l’API Web ASP.NET est plus complète et toutes les futures améliorations des fonctionnalités REST seront apportées dans l’API Web ASP.NET. »

Bien sûr au sein d’un SI ilest tout à fait possible d’utiliser les deux approches suivant les besoins propres au projet. WCF est historiquement lié au service SOAP et bien qu’apte à l’implémentation de service REST il me parait trop lourd pour la réalisation de micrososervices.

Le choix du langage : .Net Core ou .Net

Sous l’impulsion de Satya Nadella, et les nécessités d’un cloud Azure ouvert à tous les OS et à tous les langages, le projet « .NET 5 » s’est transformé en un runtime cross-plateforme et open-source connu sous le nom de « .NET Core ».

net core logo proposal - Quelles technologies .Net pour du Microservices ?

Pour des soucis de performances .Net Core semble mieux indiqué de pars sa légèreté et facilité de déploiement.

Microsoft nous propose :

« Utilisez .NET Core pour votre application serveur quand :

  • Vous avez des besoins multiplateformes ;
  • Vous ciblez des microservices ;
  • Vous utilisez des conteneurs Docker ;
  • Vous avez besoin de systèmes scalables et hautes performances.
  • Vous avez besoin de versions .NET côte à côte par application.

Utilisez .NET Framework pour votre application serveur quand :

  • Votre application utilise le .NET Framework (nous vous recommandons de privilégier l’extension à la migration).
  • Votre application utilise des packages NuGet ou des bibliothèques .NET tiers non disponibles pour .NET Core.
  • Votre application utilise des technologies .NET non disponibles pour .NET Core.
  • Votre application utilise une plateforme qui ne prend pas en charge .NET Core. »

Parenthèse sur le projet .Net Standart : Il s’agit d’une spécification pour garantir qu’une librairie de code .Net fonctionne sur toutes les plateformes. .Net Standart est donc un jeu d’API que les implémentations .Net (.Net Framework / .Net Core / Xamarin) doivent respecter pour garantir la portabilité de la librairie développée. Ce projet s’inscrit bien sûr dans la volonté de Microsoft de s’ouvrir aux autres plateformes : Linux, MacOs, Android et iOS.

dotnet tomorrow - Quelles technologies .Net pour du Microservices ?

Pour pouvoir développer en .Net Core sur les plateformes autre que Windows, Microsoft nous propose un nouvel IDE, léger, modulaire et OpenSource : https://code.visualstudio.com/. En contrepartie, ces fonctionnalités sont bien plus limitée que Visual Studio 2017.

Pour le développement de microservices en .Net la combinaison optimale me semble donc être Web API REST + .Net Core. Ce duo convient parfaitement aux besoins de légèreté, rapidité et modularité de notre architecture !