Architecture d’un microservice

Pour le développement de nos services, qui seront des composants de cette architecture :

1 1 - Architecture d'un microservice

Une bonne pratique consistera à implémenter le pattern Repository. Notre application se décomposera en 3 couches :

  • Une couche Service qui expose les points d’entrée. Elle peux être également responsable de la gestion des exceptions, de l’authentification et des logs.
  • Une couche Business qui contient la logique fonctionnelle. Elle organise les context de connexion à la base (UnitOfWork) et appelle les repository pour effectuer des opérations sur la source de données.
  • Une couche Repository qui accède ou modifie les données.

Schéma d’architecture d’un service. Les flèches en rouge représente des appels non autorisés.

1 2 - Architecture d'un microservice

Chaque couche est séparée par des interfaces pour la mise en œuvre de l’injection de dépendance dans nos projets.

A noter que Asp .Net Core supporte nativement cette bonne pratique via la classe ServiceCollection.

Au niveau des framework et outils tiers nous pourrons utiliser, en vracs  :

  • Pour l’accès aux données : l’ORM Entity Framework Core.
  • Automapper : pour mapper facilement un objet entités avec un POCO ou DTO pour le transport des informations.
  • Swagger pour la présentation de nos API. Une valeur sure !
  • Postman pour les tests locaux de communication avec notre API.
  • Nuget qu’on ne présente plus pour le partage des interfaces et des objets.
  • Nunit + Un Framework de mocking tel que Moq ou Rhino Mock pour les tests unitaires.

J’en oublie surement mais j’ai cité les indispensables 🙂

A très vite pour la partie dev !

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 !

Les architectures de services : Microservices

Nous avons présenté deux façons d’implémenter une architecture de services dans une entreprise, la première basée sur le protocole de communication SOAP est de moins en moins utilisée au détriment de la seconde basée sur REST. Une dernière implémentation est apparue récemment, adaptée aux contraintes d’agilité des systèmes d’information et à l’émergence du Cloud : les microservices.

« In short, the microservice architectural style is an approach to developing a single application as a suite of small services, each running in its own process and communicating with lightweight mechanisms, often an HTTP resource API. These services are builtaround business capabilities and independently deployable by fully automated deployment machinery. There is a bare minimum of centralized management of these services, which may be written in different programming languages and use different data storage technologies.”

Martin Fowler

Les architectures Microservices introduites par Martin Fowler dans son article : https://martinfowler.com/articles/microservices.html vont nous permettre dans un premier temps de relever les grandes idées derrière le terme de « microservice » :

  • Un composant logiciel correspondant à un besoin fonctionnel précis, définis et délimité.
  • Un composant autonome au niveau du déploiement et de l’exécution.

Un microservice est donc une unité de service fonctionnelle qui se développe, se déploie, s’exécute et gère ses données indépendamment des autres services du système.

Avec une application « monolithique », si on veut déployer une application sur un nouveau serveur il faut tout dupliquer. Avec une application en microservices, vous pouvez déployer chaque service sur 1 ou n serveurs, indépendamment des autres.

art4 - Les architectures de services : Microservices

Avantages

  • Code base indépendant : Les services sont plus simples à appréhender à développer et à repenser.
  • Les services peuvent être développés et déployés de façon plus indépendante et plus rapide.
  • Les services démarrent et s’arrêtent rapidement, ce qui réduit le temps de déploiement et améliore la productivité des développeurs.
  • Il est plus simple de mettre uniquement les composants nécessaires à l’échelle de façon dynamique pour répondre à la demande.
  • Le système tolère mieux les pannes pour une disponibilité plus élevée.
  • Les microservices peuvent être mis à niveau individuellement, en temps réel et sans interrompre le service.
  • Indépendances et agilité technologiques entre microservices.
  • Séparation des responsabilités.

La contrepartie logique de cette architecture c’est le développement, le déploiement et l’administration d’une grande quantité de services. Ainsi, si chaque service est plus simple, le système dans son ensemble est plus complexe !

Inconvénients

    • Augmentation de la complexité du SI.
    • Intégration et déploiements plus nombreux.
    • Tests plus difficiles si il y a des appels entre microservices.
    • Hausse nombre d’éléments à développer, surveiller, livrer.
    • Augmentation du trafic réseau et latence des appels HTTP.
    • Les microservices peuvent être très hétérogènes ce qui peut rendre leur implémentation plus complexe.

Si dans la théorie un microservice est un composant logiciel plutôt simple, sa mise en œuvre suscite bon nombre de questions que nous détaillerons plus tard. Dans tous les cas un certains nombres de besoins sont déjà identifiable.

Prérequis

    • Provisionnement de serveurs rapide.
    • Solution de monitoring de services.
    • Gestion des logs.
    • Maturité DevOps.
    • Gestion de configuration.
    • Tests
    • Load balancing.

3 2 300x207 - Les architectures de services : Microservices

Si nous prenons un peu de recul, on se rend compte qu’au-delà de certaines idées novatrices, la scalabilité et l’isolation des composants notamment, bon nombre des caractéristiques d’une architecture microservices se retrouvent dans une architecture de services plus classique.

Ainsi beaucoup n’hésite pas à qualifier les microservices de « buzzword » car en fin de compte on parle toujours de la même chose : une architecture de services qui s’adapte aux évolutions de l’IT au niveau du développement, des solutions d’infrastructure et même du management :

  • La SOA a mis en avant les avantages de l’approche services en entreprise.
  • L’agile et le lean startup ont fourni les modèles d’organisation des équipes pour des projets toujours plus nombreux.
  • L’industrialisation des déploiements diminue les coûts de mise en production et d’exploitation pour des mises à jours régulières.
  • L’essor du Cloud déporte les infrastructures hors du SI modifie les modèles DevOps.

Toutes ces évolutions ont selon moi aboutis à cette notion de microservices que nous mettrons bientôt en pratique !

Les architectures de services : SOA vs WOA

Après cette présentation de SOA et WOA, dans les deux précédents articles, la grande question est : Quand doit-on choisir l’un ou l’autre ?

Les deux approches, SOA et WOA, sont envisageables pour la mise en œuvre d’une architecture de services, et présentes toute deux des points forts mais également des points faibles et possèdent en fin de compte une utilisabilité propre à des environnements différents.

Tout d’abord, pour bien comprendre les avantages et inconvénients présentés plus bas voici un exemple d’appel à un webservice qui expose une méthode d’addition :

REST

Requête : GET https://mondomaine.com/sum?a=2&b=2

Réponse : 4

Documentation : La ressource « sum» est la somme de deux paramètres
a et b.

SOAP

Requête :

requete - Les architectures de services : SOA vs WOA

La réponse :

reponse - Les architectures de services : SOA vs WOA

La documentation au format wsdl :

doc - Les architectures de services : SOA vs WOA

Comparons maintenant les deux approches.

Les avantages de REST

  • Simplicité d’utilisation et de développement.
  • Opérations CRUD « native ».
  • Consommable par tous supports puisque basé sur HTTP.
  • Souplesse.

Les avantages de SOAP

  • Sécurité et fiabilité du protocole.
  • Contrats formels et rigide entre le client et le serveur.
  • Opérations avec état : partage de transaction possible.
  • Possibilité de communiquer avec un autre protocole que HTTP (TCP/IP).

De façon synthétique, REST propose une mise en œuvre simple de développement et d’utilisation, basé sur des standards connus de tous. SOAP en revanche sera utile si les contraintes de sécurité sont importantes et que le contrat entre client et services doit être absolu et strict. En 2018 la part des entreprises qui utilisent des Web API REST est de plus en plus importante.

Dans les deux cas, l’utilisation du framework .Net et du langage C# est adapté à ce besoin d’écriture de service. Le type de projet sera en revanche bien différent suivant votre choix, j’y reviendrais dans un prochain article.

Les architectures de services : WOA

Les architectures des gros noms du Web, souvent basées sur le style REST, sont, dans l’implémentation, bien différente  des SOA d’entreprises, majoritairement basées sur SOAP. Mais les APIs REST sont une forme de SOA, dont l’objectif est d’utiliser HTTP comme moyen de communication. On parle alors d’architectures orientées Web : WOA.

L’objectif de cette architecture est de proposer une version plus simple de la SOA, utilisant les caractéristiques et les standards du Web, plutôt que de chercher à les abstraire. L’architecture REST utilise les spécifications originelles du protocole HTTP, plutôt que de réinventer une surcouche comme SOAP :

  • L’URI comme identifiant des ressources.
  • Les verbes HTTP comme identifiant des opérations.
  • Les réponses HTTP comme représentation des ressources.

REST est donc fortement recommandé pour des cas simples où on cherche à effectuer des actions sur un contenu, comme lister, créer, modifier, supprimer des ressources. Pour toutes ces actions on utilisera la commande HTTP adéquat :

  • Lire une ressource, ou une collection de ressources (GET).
  • Modifier une ressource existante (PUT).
  • Créer une ressource (POST).
  • Supprimer une ressource (DELETE).

Exemple :

  • Un GET http://www.mondomaine.com/clients signifie que je souhaite récupérer la liste des clients disponibles.
  • Un GET http://www.mondomaine.com/clients/2  signifie que je souhaite récupérer les informations du client dont l’identifiant est 2.
  • Au même titre, un DELETE http://www.mondomaine.com/clients /2 doit supprimer le client 2.

Spécificités REST

Les propriétés d’une API REST sont :

Uniformité : Chaque ressource est identifiée de façon unique par son URL. L’interface est uniforme à tous les niveaux. Tous les éléments communiquent en utilisant la même interface.

Sans état : Une API REST ne doit pas maintenir de session. Cela garantis des appels idempotents.

Mise en cache : Il doit être possible d’utiliser les implémentations standards de cache HTTP.

Client / Serveur : Separation of Concerns : L’API REST n’est pas concernée par l’affichage, les interactions utilisateur et la session.

Layered : La présence de “connecteurs” intermédiaires doit être implicite pour le client et le serveur (composant de cache / sécurité etc…).

RESTFUL

En se basant sur le travail de Roy Fielding, Leonard Richardson a établi un modèle de maturité des services web REST appelé Richardson Maturity Model (RMM). Ce modèle est composé de quatre niveaux permettant d’évaluer une API par rapport aux contraintes REST.

1 1 300x177 - Les architectures de services : WOA

  • Niveau 0 : Le protocole HTTP est utilisé uniquement à des fins de transport du message. L’ensemble des données transitent par un seul et unique point d’entrée.
  • Niveau 1 : Introduction de la notion de ressources. Il y a donc désormais plusieurs endpoint (URI) par ressource.
  • Niveau 2 : Apparition de la notion d’action et d’état, ce qui correspond aux verbes, GET, POST, PUT, DELETE et aux codes http (200, 404, 500…).
  • Niveau 3 : Ultime et dernière notion de REST : HATEOAS (Hypertext As The Engine Of Application State). Notre API est « autodocumentée », c’est-à-dire que l’on peut passer d’une action à une autre via des URL transmises par l’API dans les réponses.

Une API RESTful est une API qui respecte toutes les contraintes REST. La très grande majorité du temps, les API sont au niveau 2 du RMM.