architecture microservice - difficulties
Abstract
Going microservices means increasing the overhead on infrastructure IT resources, devops expertise, monitoring, deployment mangement, …
Microservices architecture can also be perceived as a “hype” because “everyone are doing it”.
Go monolith first, then splitting into multiple microservices by refactoring the application and splitting the technical and functional domain responsibilities correctly.
Going microservices also means:
- longer and harder to orchestrate end to end tests
- hader to debug (multiple logs to check)
- add effort on cross team communications
- data responsibilities
- latency (microservices ⇒ need to pay the network communication price)
Introduction
Je suis confiné avec ma famille et mes collègues aussi. Ce dernier point est crucial pour la suite de l’article, car le corollaire est que je deviens intouchable physiquement, je vais pouvoir critiquer les architectures microservices au chaud et mes collègues ne pourront pas venir me casser les genoux à la récré. J’aviserai comment gérer mes genoux et mon retour à la vie sociale un peu plus tard ;-)
Note : Cet article propose les grands principes d’une architecture microservices et ce que cela implique dans un SI. Vous y trouverez des basiques, qui sont utiles aux néophytes mais aussi aux plus experts pour qui un rappel fait parfois du bien. Nous passerons en revue les grands types de questions qu’il nous paraît indispensables de poser avant d’adopter les architectures microservices.
Il y a 5 ans Martin Fowler en parlait déjà et en 2020, nous avons désormais du recul sur les architectures microservices. Nous savons qu’elles sont pertinentes dans certains contextes où on a besoin de modularité, de performance et / ou d’indépendance des équipes. Nous savons aussi que ce ne sont pas des “silver bullets”. Enfin et surtout nous savons qu’en simplifiant chaque service elles repoussent la complexité dans l’intégration inter services et augmentent ainsi l’entropie des SI. Pour mieux sentir cette complexité, rappelons que dans ce type d’architecture chaque service s’apparente à une application dans l’idéal autonome.
Toutes les problématiques d‘intégration inter-applications que vous avez pu croiser par le passé dans votre SI vous les retrouvez au beau milieu de ce type d’architecture autour de chaque microservice.
Les architectures microservice augmentent le nombre d’applications qu’il faut maintenir en cohérence, gérer en déploiement et en monitoring. Les besoins en ressources infra IT, les besoins en compétences devops et en architecture d’intégration dans le SI augmentent.
La question est donc de savoir si dans votre contexte cela en vaut la peine et si vous êtes en mesure de pouvoir vous l’offrir ?
Les architectures microservices, c’est un peu trop fort pour toi mon p’tit gars ! (src : pub KissCool)
Illustration chez un client
En pleine mission avec mon collègue Nalian, lors d’un audit d’une application, nous abordons une architecture microservices et au fil de nos discussions nous évoquons avec le client la complexité de ce type d’architecture. En questionnant ses choix nous trouvons que ses microservices sont parfois bien petits, avec de fortes dépendances fonctionnelles et sans enjeux systématique de performance sur les domaines couverts.
Bref, nous trouvons qu’il y a beaucoup de complexité, ce qui demande d’avoir un très bon niveau en architecture IT sans pour autant être adapté à son contexte.
Un phénomène de mode, parfois utile, mais qu’il faut pouvoir se payer
Il faut dire que les architectures microservices sont à la mode et elles font kiffer les développeurs. Les géants du web sont passés par là aussi… Leurs ingénieur(e)s qui ont mis ces architectures en place l’ont fait parce qu’ils ont rencontré des limites d’indépendance des équipes (i.e. dans la maintenabilité des applications), de rapidité de déploiement, de performance ou de scalabilité avec les architectures “plus classiques”. Ces limites ne sont pas systématiques ou aussi criantes dans les applications que nous croisons. Pourquoi alors mettre des architectures microservices dans des contextes moins exigeants ?
Principalement, parce que les géants du web ont appris de ces nouveaux paradigmes d’architecture, ils en ont tiré des bénéfices bien réels dans des contextes d’usages clairs. En communiquant leurs avancées, ces nouvelles architectures ont alors bénéficié d’une visibilité auprès d’un large public. La mode était lancée et moi aussi ‘je veux mon architecture microservices’. Qu’importe si c’est adapté ou non, c’est hype, les géants du web en ont mis en place, ça marche et cela peut me permettre d’attirer des développeurs dans mon organisation déjà bien à la peine pour les recruter.
En faisant entrer les architectures microservices dans leurs organisations, ces dernières trouvent certes un moyen d’attirer des développeurs(ses) mais elles n’ont pas toujours conscience que le collectif d’ingénieur(e)s recruté(e)s devra avoir une maturité en matière d’IT bien plus élevée. Les architectures microservices sont en effet beaucoup plus complexes, dans des mains moins expertes le résultat est potentiellement catastrophique. La rareté et la volatilité de ces profils sont bien plus élevées sur le marché et mécaniquement leurs salaires aussi.
Les gains, la complexité mais aussi la taille compte
Voici plus en détail les enjeux et problématiques soulevés par une architecture en microservices.
Les architectures microservices permettent de faire scaler individuellement des composants….mais ai-je besoin de cette possibilité au moment où je me lance ?
Ne puis-je pas démarrer avec une application monolithique en mettant l’effort sur une bonne modularité interne permettant de sortir plus tard les composants qui auront besoin de scalabilité ?
Les architectures microservices permettent de gagner en modularité.
Si mon produit est très gros (vous avez dit “monolithe” ?) on pourrait vouloir le découper techniquement en microservices de manière à faciliter par exemple la mise en production partielle (l.e. les microservices qui évoluent). En effet, certaines parties évoluent plus vite que d’autres et si je gagne en indépendance alors je peux faire évoluer et mettre en production certaines parties beaucoup plus vite que d’autres.
Cette approche est peut-être plus facile à mettre en place à posteriori lorsque j’aurai emmagasiné une expérience de mon application et que la granularité du découpage aura émergé plus naturellement. Toutefois, si je veux me faciliter la tâche plus tard j’ai plutôt intérêt à construire et à refactorer mon application en séparant bien les domaines de responsabilités techniques et fonctionnels. Toute forme d’imbrications augmentant la difficulté de découpage ultérieur.
Ai-je besoin de distribuer des transactions sur plusieurs services ?
Si vous pensez répondre oui à cette question, alors en tant qu’architecte vous devriez commencer à transpirer et repenser à la granularité de vos microservices. Si les services sont couplés par nature, les découpler en microservices sera vite un enfer à gérer pour maintenir la cohérence entre services. La gestion de la désynchronisation et les mécanismes pour les éviter consommeront beaucoup de vos ressources en développement (process d’update distribués, suivi de cohérence et mécanisme de compensation pour revenir en arrière si besoin).
- Le corollaire est que les tests bout en bout seront plus longs et difficiles à orchestrer via des outils.
- Le deuxième corollaire est que pour débugger il faut aller “jardiner” dans autant de fichiers de logs qu’il y a de services impliqués. Consolider et corréler des logs de services fait désormais partie de vos préoccupations supplémentaires. Cela devient même un incontournable pour des architectures microservices qui fonctionnent. A compléter avec un monitoring des flux entre les microservices.
- Le troisième corollaire est organisationnel. Si mes équipes sont distribuées alors une problématique d’intégration entre les systèmes et les équipes via des contrats d’interfaces est à mettre en place. Un design d’API par approche REST exposant uniquement des ressources permettra de faciliter les échanges mais cela nécessite des efforts d’intégration techniques et entre les équipes. Ces dernières doivent s’entendre sur les signatures des services, le mode de communication (asynchrone ou synchrone), leur sécurité, la gestion des exceptions, sur comment mocker les services puis les tester de bout en bout. On parle bien ici d’enjeux d’intégration applicatives et techniques entre microservices.
Ai-je besoin de partager des données entre mes services ?
Là encore si vous pensez en avoir besoin, une rigueur supplémentaire s’impose quant à la gestion de la propriété des données, la garantie de leur cohérence, leur réplication ou plus généralement leur exposition entre services. Partager des données est bel et bien une problématique d’intégration.
Evaluez bien jusqu’à quelle granularité vos microservices doivent descendre. Si les services constituant votre application sont couplés par nature, les découpler en microservices sera vite un enfer à gérer pour maintenir toute cohérence entre eux. En cas de nombreux appels se posera aussi la question de la performance qu’on abordera au point suivant.
En résumé, plus votre application est susceptible d’exposer des services couplés, plus grosse la granularité des microservices sera. Mieux vaut bien évaluer à l’avance et si le gain (modularité, indépendance des équipes, performance, …) n’est pas évident, mieux vaut limiter les flux de partage et de synchronisation de données entre microservices.
La latence est-elle un enjeu ?
Y a-t-il de nombreuses communications interservices ? Si les services sont supposés communiquer entre eux alors passer d’une transaction en mémoire à une communication basée sur le réseau induira des latences globalement 1000 fois plus lentes (source : latency numbers every programmer should know) .
Êtes-vous armés en devops ?
Dans une architecture microservice fortement distribuée les services doivent être déployés indépendamment sur la base de plusieurs machines virtuelles ou conteneurs. Vous ne pouvez pas maintenir et surveiller les microservices sans la présence d’une équipe devops efficace et industrielle. Cela a un coût d’autant plus que ces compétences sont rares et chères. Le monitoring des flux lui aussi demande un niveau de maturité pour le mettre en place et en faire le suivi.
Conclusion
Alors, faut-il abandonner les architectures microservices ? Non, mais commencer un projet directement avec me semble souvent risqué dans les cas que nous rencontrons chez nos clients – majoritairement des grandes entreprises ou des ETI. En revanche, démarrer en monolithe quitte à le découper plus tard est une approche plus pragmatique – et ce n’est pas moi qui le dit mais Martin Fowler qui l’a constaté les architectures microsservices qui ont réussi sont d’abord parties d’un monolithe (confirmation de la loi de Gall).
L’apprentissage de l’usage étant crucial pour savoir comment découper son architecture, il faut préparer le découpage et correctement séparer les zones de responsabilités entre les différentes couches métiers et aussi techniques. Il n’y a rien de magique un monolithe imbriqué sera difficilement transformable en architecture microservices. Ensuite, appliquer ce type d’architecture de manière dogmatique vous fera courir à votre perte. Ce n’est qu’une option parmi d’autres optimisations comme par exemple celles que vous pourriez appliquer directement sur le monolithe. Enfin, si vous vous lancez, adaptez ses concepts à vos besoins comme le choix domaines fonctionnels à découper, la taille des microservices et évaluez l’impact que cela aura sur votre SI. Enfin, évaluez les compétences nécessaires pour le faire tourner.
Pour en revenir à nos Géants du Web, les communautés travaillent pour aider à gérer ces difficultés et notamment via l’outillage, ce qui permet de faire plus facilement de microservices maintenant qu’il y a 4 ou 5 ans, en particulier il y a :
- Une plus grande maturité de la conteneurisation avec Docker et Kubernetes qui se sont imposés comme des standards du marché
- Une multiplication des services managés permettant de simplifier la création et la gestion des multiples assets utilisés par les microservices : base de données, cache, services de messageries (gestion des abonnements – Pub/Sub – gestion de files de d’attente/persistance)
- Une plus grande maturité des solutions pour la gestion des APIs pour gérer les interfaces des microservices
- Une amélioration des systèmes de registre qui facilite la localisation dynamique des microservices entre eux
Ces outils comme tous les outils nécessitent une maîtrise des concepts sous-jacents et plus d’outils c’est toujours plus de complexité.
A emporter
L’entropie potentielle d’une architecture microservices est plus élevée qu’une architecture classique.
Chaque service s’apparente à une application relativement autonome. Chaque application exige des équipes et des ressources minimums d’infrastructure pour la faire fonctionner.
Démarrer en monolithe et découper plus tard en microservices est une approche plus pragmatique.
Ne négligez pas tous les travaux d’optimisation de votre monolithe avant de partir sur une architecture microservices.
Si l’entropie du SI augmente, le nombre et le niveau de compétences exigées monte en conséquence. Attirer les talents par les architectures microservices, pourquoi pas mais prenez conscience que le collectif d’ingénieur(e)s à recruter devra avoir une maturité en matière d’IT bien plus élevée que sur des architectures classiques. Dans des mains moins expertes le résultat est potentiellement catastrophique. Voyez si vous êtes en mesure de vous les payer puis de les garder dans votre organisation ou de faire monter en compétences d’autres profils.
Le coût global en ressources est plus élevé qu’une architecture classique pour faire fonctionner l’ensemble.