{"id":35906,"date":"2019-10-31T22:07:29","date_gmt":"2019-10-31T19:07:29","guid":{"rendered":"https:\/\/prohoster.info\/blog\/perehod-ot-monolita-k-mikroservisam-istoriya-i-praktika\/"},"modified":"2019-10-31T22:07:29","modified_gmt":"2019-10-31T19:07:29","slug":"perehod-ot-monolita-k-mikroservisam-istoriya-i-praktika","status":"publish","type":"post","link":"https:\/\/prohoster.info\/fr\/blog\/administrirovanie\/perehod-ot-monolita-k-mikroservisam-istoriya-i-praktika","title":{"rendered":"Transition du monolithe vers les micros-services : histoire et pratique","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Dans cet article, je vais vous parler de la fa\u00e7on dont le projet sur lequel je travaille est pass\u00e9 d'un grand monolithe \u00e0 un ensemble de microservices.<\/p>\n<p>Le projet a commenc\u00e9 son histoire il y a longtemps, au d\u00e9but des ann\u00e9es 2000. Les premi\u00e8res versions ont \u00e9t\u00e9 \u00e9crites en Visual Basic 6. Au fil du temps, il est devenu clair que le d\u00e9veloppement dans ce langage serait difficile \u00e0 maintenir \u00e0 l'avenir, car l'IDE et le langage lui-m\u00eame \u00e9voluent lentement. \u00c0 la fin des ann\u00e9es 2000, il a \u00e9t\u00e9 d\u00e9cid\u00e9 de passer \u00e0 un C# plus prometteur. La nouvelle version a \u00e9t\u00e9 d\u00e9velopp\u00e9e parall\u00e8lement \u00e0 l'ancienne, de plus en plus de code \u00e9tant \u00e9crit en .NET. Le backend en C# \u00e9tait initialement orient\u00e9 vers une architecture de services, mais durant le d\u00e9veloppement, des biblioth\u00e8ques communes \u00e9taient utilis\u00e9es, et les services \u00e9taient lanc\u00e9s dans un m\u00eame processus. Cela a donn\u00e9 un applicatif que nous appelions \u00ab monolithe de services \u00bb. <\/p>\n<p>L'un des rares avantages de cette combinaison \u00e9tait la possibilit\u00e9 pour les services de s'appeler mutuellement via une API externe. Il y avait des incitations claires \u00e0 passer \u00e0 une architecture de services plus correcte, et \u00e0 terme, \u00e0 une architecture microservices. <\/p>\n<p>Nous avons commenc\u00e9 notre travail de d\u00e9composition vers 2015. Bien que nous n'ayons pas encore atteint un \u00e9tat id\u00e9al \u2014 il reste des parties du grand projet qui sont d\u00e9j\u00e0 difficiles \u00e0 appeler des monolithes, mais qui ne ressemblent pas non plus \u00e0 des microservices. Cependant, les progr\u00e8s sont significatifs. <br \/>\nC'est ce dont je parlerai dans cet article.<\/p>\n<p><img decoding=\"async\" alt=\"Transition du monolithe vers les micros-services : histoire et pratique\" src=\"\/wp-content\/uploads\/2019\/07\/132bb4ea6b9dbcdd202ee090f2b86289.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h3>Contenu<\/h3>\n<p><\/p>\n<ul>\n<li><noindex><a rel=\"nofollow\" href=\"#1\"> Architecture et probl\u00e8mes de la solution existante<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#2\">Attentes vis-\u00e0-vis des microservices<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#3\">Probl\u00e8mes de transition<\/a><\/noindex><\/li>\n<li> <noindex><a rel=\"nofollow\" href=\"#4\">Comment passer du monolithe aux microservices<\/a><\/noindex>\n<ul>\n<li><noindex><a rel=\"nofollow\" href=\"#5\">Premi\u00e8re m\u00e9thode<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#6\">Deuxi\u00e8me m\u00e9thode<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#7\">Troisi\u00e8me m\u00e9thode<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#8\">Quatri\u00e8me m\u00e9thode<\/a><\/noindex><\/li>\n<\/ul>\n<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#9\">Travailler avec la BDD<\/a><\/noindex>\n<ul>\n<li><noindex><a rel=\"nofollow\" href=\"#10\">S\u00e9paration des tables existantes<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#11\">S\u00e9paration avec refonte<\/a><\/noindex><\/li>\n<\/ul>\n<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#12\">Travail sur le code source<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#13\">Probl\u00e8mes d'infrastructure<\/a><\/noindex>\n<ul>\n<li><noindex><a rel=\"nofollow\" href=\"#16\">Installation manuelle dans les environnements<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#14\">Journalisation s\u00e9par\u00e9e<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#15\">Tests et d\u00e9bogage des services interconnect\u00e9s<\/a><\/noindex><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p><noindex><a rel=\"nofollow\" name=\"1\"><\/a><\/noindex><b><\/p>\n<h3>Architecture et probl\u00e8mes de la solution existante<\/h3>\n<p><\/b><br \/>\n\u00c0 l'origine, l'architecture \u00e9tait la suivante : l'UI \u00e9tait une application distincte, la partie monolithique \u00e9tait \u00e9crite en Visual Basic 6, et l'application .NET \u00e9tait un ensemble de services interconnect\u00e9s fonctionnant avec une base de donn\u00e9es assez importante.<\/p>\n<p><b>Inconv\u00e9nients de la solution pr\u00e9c\u00e9dente<\/b><\/p>\n<p><u>Point de d\u00e9faillance unique<\/u><br \/>\nNous avions un point unique de d\u00e9faillance : l'application .NET s'ex\u00e9cutait dans un seul processus. Si l'un des modules \u00e9chouait, l'ensemble de l'application tombait, et il fallait la red\u00e9marrer. \u00c9tant donn\u00e9 que nous automatisons un grand nombre de processus pour diff\u00e9rents utilisateurs, une d\u00e9faillance dans l'un d'eux emp\u00eachait tout le monde de travailler pendant un certain temps. Et en cas d'erreur logicielle, la redondance ne servait \u00e0 rien. <\/p>\n<p><u>File d'attente des am\u00e9liorations<\/u><br \/>\nCe d\u00e9faut est plut\u00f4t organisationnel. Notre application compte de nombreux clients, et tous souhaitent l'am\u00e9liorer le plus rapidement possible. Auparavant, il \u00e9tait impossible de le faire en parall\u00e8le, et tous les clients faisaient la queue. Ce processus suscita des frustrations au sein de l'entreprise, car ils devaient prouver que leur t\u00e2che avait de la valeur. Pendant ce temps, l'\u00e9quipe de d\u00e9veloppement passait du temps \u00e0 organiser cette file d'attente. Cela prenait beaucoup de temps et d'\u00e9nergie, et le produit ne pouvait finalement pas \u00e9voluer aussi rapidement que souhait\u00e9.<\/p>\n<p><u>Utilisation non optimale des ressources<\/u><br \/>\nLors de l'h\u00e9bergement des services dans un processus unique, nous copions toujours int\u00e9gralement la configuration d'un serveur \u00e0 l'autre. Nous souhaitions h\u00e9berger les services les plus charg\u00e9s s\u00e9par\u00e9ment, afin de ne pas gaspiller les ressources, et obtenir une gestion plus flexible de notre sch\u00e9ma de d\u00e9ploiement.<\/p>\n<p><u>Difficult\u00e9 \u00e0 int\u00e9grer les technologies modernes<\/u><br \/>\nUn probl\u00e8me connu de tous les d\u00e9veloppeurs : il y a un d\u00e9sir d'int\u00e9grer des technologies modernes dans le projet, mais aucune possibilit\u00e9. Avec une solution monolithique importante, toute mise \u00e0 jour de la biblioth\u00e8que actuelle, sans parler d'un passage \u00e0 une nouvelle, devient une t\u00e2che assez complexe. Il faut longtemps prouver \u00e0 l'\u00e9quipe que cela apportera plus d'avantages que de stress. <\/p>\n<p><u>Complexit\u00e9 de la livraison des changements<\/u><br \/>\nC'\u00e9tait le probl\u00e8me le plus s\u00e9rieux \u2014 nous publiions des versions tous les deux mois. <br \/>\nChaque version se transformait en v\u00e9ritable catastrophe pour la banque, malgr\u00e9 les tests et les efforts des d\u00e9veloppeurs. L'entreprise comprenait qu'une partie de la fonctionnalit\u00e9 ne fonctionnerait pas au d\u00e9but de la semaine. Les d\u00e9veloppeurs, quant \u00e0 eux, savaient qu'ils allaient faire face \u00e0 une semaine d'incidents s\u00e9rieux. <br \/>\nLe d\u00e9sir de changer la situation \u00e9tait partag\u00e9 par tous. <\/p>\n<p><noindex><a rel=\"nofollow\" name=\"2\"><\/a><\/noindex><b><\/p>\n<h3>Attentes vis-\u00e0-vis des microservices<\/h3>\n<p><\/b><br \/>\n<u>Livraison des composants selon leur disponibilit\u00e9. <\/u>Livraison des composants au fur et \u00e0 mesure de leur pr\u00e9paration gr\u00e2ce \u00e0 la d\u00e9composition de la solution et \u00e0 la s\u00e9paration des diff\u00e9rents processus.<\/p>\n<p><u>De petites \u00e9quipes produit.<\/u> C'est important, car il est difficile de g\u00e9rer une grande \u00e9quipe travaillant sur un ancien monolithe. Une telle \u00e9quipe doit suivre un processus strict, tandis qu'on aspire \u00e0 plus de cr\u00e9ativit\u00e9 et d'ind\u00e9pendance. Cela ne peut \u00eatre permis qu'aux petites \u00e9quipes.<\/p>\n<p><u>Isolation des services dans des processus distincts.<\/u> Id\u00e9alement, nous aimerions isoler dans des conteneurs, mais un grand nombre de services \u00e9crits en .NET Framework ne s'ex\u00e9cutent que sous Windows. Des services sur .NET Core \u00e9mergent, mais ils sont encore peu nombreux.<\/p>\n<p><u>Flexibilit\u00e9 de d\u00e9ploiement.<\/u> Nous aimerions combiner les services comme cela est n\u00e9cessaire pour nous, et non comme le code l'impose.<\/p>\n<p><u>Utilisation de nouvelles technologies.<\/u> C'est int\u00e9ressant pour tout programmeur.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"3\"><\/a><\/noindex><b><\/p>\n<h3>Probl\u00e8mes de transition<\/h3>\n<p><\/b><br \/>\nBien s\u00fbr, si d\u00e9composer un monolithe en microservices \u00e9tait facile, il n'y aurait pas besoin d'en parler lors des conf\u00e9rences et d'\u00e9crire des articles. Ce processus comporte de nombreux pi\u00e8ges; je vais d\u00e9crire les principaux qui nous ont g\u00ean\u00e9s.<\/p>\n<p><b>Le premier probl\u00e8me<\/b> caract\u00e9ristique de la plupart des monolithes : la coh\u00e9rence de la logique m\u00e9tier. Lorsque nous \u00e9crivons un monolithe, nous souhaitons r\u00e9utiliser nos classes pour \u00e9viter d'\u00e9crire du code inutile. En passant aux microservices, cela devient un probl\u00e8me : tout le code est assez rigidement li\u00e9, rendant difficile la s\u00e9paration des services.<\/p>\n<p>Au moment o\u00f9 nous avons commenc\u00e9 \u00e0 travailler, il y avait plus de 500 projets dans le r\u00e9f\u00e9rentiel et plus de 700 000 lignes de code. C'est une solution suffisamment grande et <b>le deuxi\u00e8me probl\u00e8me<\/b>. Prendre la d\u00e9cision de le diviser en microservices s'est r\u00e9v\u00e9l\u00e9 impossible.<\/p>\n<p><b>Le troisi\u00e8me probl\u00e8me<\/b> \u2014 manque d'infrastructure n\u00e9cessaire. En fait, nous \u00e9tions engag\u00e9s dans une copie manuelle du code source sur les serveurs.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"4\"><\/a><\/noindex><b><\/p>\n<h3>Comment passer du monolithe aux microservices<\/h3>\n<p><\/b><br \/>\n<u>D\u00e9doublage des microservices<\/u><\/p>\n<p>Tout d'abord, nous avons imm\u00e9diatement d\u00e9fini que la s\u00e9paration des microservices est un processus it\u00e9ratif. On exigeait toujours de nous de mener parall\u00e8lement le d\u00e9veloppement des t\u00e2ches commerciales. Comment nous allons proc\u00e9der techniquement \u2014 c'est notre probl\u00e8me. Nous nous pr\u00e9parions donc \u00e0 un processus it\u00e9ratif. Il n'y a pas d'autre moyen si vous avez une grande application qui n'est pas initialement pr\u00eate \u00e0 \u00eatre r\u00e9\u00e9crite.<\/p>\n<p>Quelles m\u00e9thodes utilisons-nous pour isoler les microservices?<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"5\"><\/a><\/noindex><b>Premi\u00e8re m\u00e9thode <\/b>\u2014 extraire les modules existants en tant que services. \u00c0 cet \u00e9gard, nous avons eu de la chance : il y avait d\u00e9j\u00e0 des services configur\u00e9s qui utilisaient le protocole WCF. Ils \u00e9taient r\u00e9partis dans des assemblies distinctes. Nous les transfusions s\u00e9par\u00e9ment, ajoutant \u00e0 chaque assembly un petit module de d\u00e9marrage. Ce dernier \u00e9tait \u00e9crit avec l'incroyable biblioth\u00e8que Topshelf, qui permet de lancer l'application \u00e0 la fois en tant que service et en tant que console. C'est pratique pour le d\u00e9bogage, car aucun projet suppl\u00e9mentaire dans la solution n'est n\u00e9cessaire.<\/p>\n<p>Les services \u00e9taient li\u00e9s par la logique m\u00e9tier, car ils utilisaient des assemblies communes et manipulaient une base de donn\u00e9es partag\u00e9e. Il \u00e9tait difficile de les qualifier de microservices au sens strict. Cependant, nous pouvions \u00e9tablir ces services s\u00e9par\u00e9ment, dans des processus diff\u00e9rents. Cela a d\u00e9j\u00e0 permis de r\u00e9duire l'influence qu'ils exercent les uns sur les autres, diminuant ainsi les probl\u00e8mes li\u00e9s au d\u00e9veloppement parall\u00e8le et au point de d\u00e9faillance unique.<\/p>\n<p>L'assembly avec l'h\u00f4te ne n\u00e9cessite qu'une ligne de code dans la classe Program. Nous avons cach\u00e9 l'utilisation de Topshelf dans une classe auxiliaire.<\/p>\n<pre><code class=\"plaintext\">namespace RBA.Services.Accounts.Host\n{\n   internal class Program\n   {\n      private static void Main(string[] args)\n      {\n        HostRunner.Run(\"RBA.Services.Accounts.Host\");\n\n       }\n    }\n}\n<\/code><\/pre>\n<p>\n<noindex><a rel=\"nofollow\" name=\"6\"><\/a><\/noindex><b>La deuxi\u00e8me m\u00e9thode de d\u00e9finition des microservices :<\/b> les cr\u00e9er pour r\u00e9soudre de nouveaux probl\u00e8mes. Si le monolithe ne grandit pas dans ce cas, c'est d\u00e9j\u00e0 un bon signe, cela signifie que nous avan\u00e7ons dans la bonne direction. Pour des t\u00e2ches nouvelles, nous essayions de cr\u00e9er des services distincts. Quand c'\u00e9tait possible, nous formions des services plus \"canoniques\", qui g\u00e8rent compl\u00e8tement leur propre mod\u00e8le de donn\u00e9es, et poss\u00e8dent leur propre base de donn\u00e9es. <\/p>\n<p>Comme beaucoup d'autres, nous avons commenc\u00e9 par des services d'authentification et d'autorisation. Ils conviennent parfaitement \u00e0 cet usage. Ils sont ind\u00e9pendants, en g\u00e9n\u00e9ral, poss\u00e8dent un mod\u00e8le de donn\u00e9es distinct. Ils n'interagissent pas avec le monolithe, seulement celui-ci les sollicite pour r\u00e9soudre certaines t\u00e2ches. Ces services peuvent servir de point de d\u00e9part pour la transition vers une nouvelle architecture, pour affiner l'infrastructure, essayer certaines approches li\u00e9es aux biblioth\u00e8ques r\u00e9seau, etc. Dans notre organisation, il n'y a pas d'\u00e9quipes qui n'ont pas r\u00e9ussi \u00e0 cr\u00e9er un service d'authentification. <\/p>\n<p><noindex><a rel=\"nofollow\" name=\"7\"><\/a><\/noindex><b>La troisi\u00e8me m\u00e9thode de d\u00e9finition des microservices<\/b>, qui nous concerne, est un peu sp\u00e9cifique \u00e0 nous. C'est l'extraction de la logique m\u00e9tier de la couche UI. Notre application principale UI est desktop, et, tout comme le backend, elle est \u00e9crite en C#. Les d\u00e9veloppeurs font parfois des erreurs et d\u00e9placent vers l'UI des parties de la logique qui devraient exister dans le backend et \u00eatre r\u00e9utilis\u00e9es. <\/p>\n<p>Si l'on regarde un exemple r\u00e9el du code de la partie UI, on peut voir que la majeure partie de cette solution contient de la v\u00e9ritable logique m\u00e9tier, qui est utile dans d'autres processus, pas seulement pour construire des formulaires UI. <\/p>\n<p><img decoding=\"async\" alt=\"Transition du monolithe vers les micros-services : histoire et pratique\" src=\"\/wp-content\/uploads\/2019\/07\/74c7b90ff94b343816ab3ac2fa0673c6.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nIl n'y a que les derni\u00e8res lignes de v\u00e9ritable logique UI. Nous l'avons transf\u00e9r\u00e9e sur le serveur afin de pouvoir la r\u00e9utiliser, r\u00e9duisant ainsi l'UI et atteignant une architecture correcte.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"8\"><\/a><\/noindex><b>La quatri\u00e8me et plus importante m\u00e9thode d'extraction des microservices<\/b>, qui permet de r\u00e9duire le monolithe, est l'extraction des services existants avec une refonte. Lorsque nous extrayons des modules existants tels quels, le r\u00e9sultat n'est pas toujours satisfaisant pour les d\u00e9veloppeurs, et le processus m\u00e9tier depuis la cr\u00e9ation de la fonctionnalit\u00e9 peut \u00eatre obsol\u00e8te. Gr\u00e2ce au refactoring, nous pouvons supporter un nouveau processus m\u00e9tier, car les exigences commerciales changent constamment. Nous pouvons am\u00e9liorer le code source, \u00e9liminer les d\u00e9fauts connus, cr\u00e9er un mod\u00e8le de donn\u00e9es de meilleure qualit\u00e9. Cela apporte de nombreux avantages.<\/p>\n<p>La s\u00e9paration des services avec refonte est inextricablement li\u00e9e au concept de contexte limit\u00e9. Ce concept vient du design orient\u00e9 domaine. Il signifie une zone du mod\u00e8le de domaine o\u00f9 tous les termes d'un langage commun sont clairement d\u00e9finis. Prenons l'exemple du contexte des assurances et des factures. Nous avons une application monolithique et il est n\u00e9cessaire de travailler sur la facture dans le domaine des assurances. Nous nous attendons \u00e0 ce que le d\u00e9veloppeur trouve dans un autre assemblage la classe existante \u00ab Facture \u00bb, \u00e9tablisse un lien vers celle-ci depuis la classe \u00ab Assurance \u00bb, et nous obtiendrons un code fonctionnel. Le principe DRY sera respect\u00e9, et la t\u00e2che sera accomplie plus rapidement gr\u00e2ce \u00e0 l'utilisation de code existant.<\/p>\n<p>Il s'av\u00e8re que les contextes des comptes et des assurances sont li\u00e9s. Lorsque de nouvelles exigences appara\u00eetront, ce lien compliquera le d\u00e9veloppement, augmentant ainsi la complexit\u00e9 d'une logique m\u00e9tier d\u00e9j\u00e0 complexe. Pour r\u00e9soudre ce probl\u00e8me, il est n\u00e9cessaire d'identifier les limites entre les contextes dans le code et d'\u00e9liminer leurs violations. Par exemple, pour le contexte des assurances, il sera probablement suffisant d'avoir un num\u00e9ro de compte de 20 chiffres de la banque centrale et la date d'ouverture du compte. <\/p>\n<p>Pour s\u00e9parer ces contextes limit\u00e9s et commencer le processus d'extraction de microservices d'une solution monolithique, nous avons adopt\u00e9 une approche consistant \u00e0 cr\u00e9er des API externes \u00e0 l'int\u00e9rieur de l'application. Si nous savions qu'un module devait devenir un microservice ou se modifier dans le cadre du processus, nous faisions imm\u00e9diatement appel \u00e0 la logique appartient \u00e0 un autre contexte limit\u00e9 via des appels externes, par exemple, via REST ou WCF.<\/p>\n<p>Nous avons d\u00e9cid\u00e9 fermement de ne pas \u00e9viter le code qui n\u00e9cessiterait de r\u00e9aliser des transactions distribu\u00e9es. Dans notre cas, il s'est av\u00e9r\u00e9 relativement facile de respecter cette r\u00e8gle. Nous n'avons jusqu'\u00e0 pr\u00e9sent pas rencontr\u00e9 de situations o\u00f9 des transactions distribu\u00e9es strictes seraient r\u00e9ellement n\u00e9cessaires - il suffit d'avoir une coh\u00e9rence finale entre les modules.<\/p>\n<p>Consid\u00e9rons un exemple concret. Nous avons un concept d'orchestrateur - un pipeline qui traite l'entit\u00e9 \"demande\". Il cr\u00e9e successivement un client, un compte et une carte bancaire. Si le client et le compte sont cr\u00e9\u00e9s avec succ\u00e8s, mais la cr\u00e9ation de la carte \u00e9choue, la demande ne passe pas au statut \"r\u00e9ussie\" et reste au statut \"carte non cr\u00e9\u00e9e\". \u00c0 l'avenir, une activit\u00e9 en arri\u00e8re-plan la reprendra et la finira. Le syst\u00e8me se trouve pendant un certain temps dans un \u00e9tat d'incoh\u00e9rence, mais cela ne nous d\u00e9range pas fondamentalement.<\/p>\n<p>Dans le cas o\u00f9 une situation se pr\u00e9senterait o\u00f9 il serait n\u00e9cessaire de sauvegarder certaines donn\u00e9es de mani\u00e8re coh\u00e9rente, nous opterons probablement pour une agr\u00e9gation du service afin de traiter cela en un seul processus. <\/p>\n<p>Consid\u00e9rons un exemple d'extraction d'un microservice. Comment peut-on l'amener relativement en toute s\u00e9curit\u00e9 en production ? Dans cet exemple, nous avons une partie distincte du syst\u00e8me - un module de gestion des paies, dont l'un des segments de code que nous aimerions transformer en microservice.<\/p>\n<p><img decoding=\"async\" alt=\"Transition du monolithe vers les micros-services : histoire et pratique\" src=\"\/wp-content\/uploads\/2019\/07\/346af271b0c3f99897d330e56f713f18.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nTout d'abord, nous cr\u00e9ons un microservice en r\u00e9\u00e9crivant le code. Nous am\u00e9liorons certains aspects qui ne nous convenaient pas. Nous mettons en \u0153uvre de nouvelles exigences m\u00e9tier du client. Nous ajoutons une API Gateway dans le lien entre l'interface utilisateur et le backend, qui assurera le passage des appels. <\/p>\n<p><img decoding=\"async\" alt=\"Transition du monolithe vers les micros-services : histoire et pratique\" src=\"\/wp-content\/uploads\/2019\/07\/bec8d68f20f3ec53af0cef225a51c2b3.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nEnsuite, nous d\u00e9ployons cette configuration en production, mais dans un \u00e9tat pilote. La plupart de nos utilisateurs continuent d'utiliser les anciens processus m\u00e9tier. Pour les nouveaux utilisateurs, nous d\u00e9veloppons une nouvelle version de l'application monolithique, qui ne contient plus ce processus. En essence, nous faisons fonctionner en pilote le lien entre le monolithe et le microservice.<\/p>\n<p><img decoding=\"async\" alt=\"Transition du monolithe vers les micros-services : histoire et pratique\" src=\"\/wp-content\/uploads\/2019\/07\/27e98812746bb7f142fa3a3c3a03b52f.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nLors du succ\u00e8s du pilote, nous r\u00e9alisons que la nouvelle configuration est r\u00e9ellement fonctionnelle, nous pouvons retirer l'ancien monolithe de l'\u00e9quation et laisser la nouvelle configuration \u00e0 la place de l'ancienne solution.<\/p>\n<p><img decoding=\"async\" alt=\"Transition du monolithe vers les micros-services : histoire et pratique\" src=\"\/wp-content\/uploads\/2019\/07\/11dcf1d771b57d3921c0aa91b82646e1.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nEn r\u00e9sum\u00e9, nous utilisons pratiquement toutes les m\u00e9thodes existantes de s\u00e9paration du code source du monolithe. Toutes permettent de r\u00e9duire la taille des parties de l'application et de les migrer vers de nouvelles biblioth\u00e8ques, am\u00e9liorant ainsi la qualit\u00e9 du code source.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"9\"><\/a><\/noindex><b><\/p>\n<h3>Travailler avec la BDD<\/h3>\n<p><\/b><br \/>\nLa base de donn\u00e9es est plus difficile \u00e0 s\u00e9parer que le code source, car elle contient non seulement le sch\u00e9ma actuel, mais aussi des donn\u00e9es historiques accumul\u00e9es.<\/p>\n<p>Notre base de donn\u00e9es, comme beaucoup d'autres, avait un autre inconv\u00e9nient majeur : une taille \u00e9norme. Cette base de donn\u00e9es a \u00e9t\u00e9 con\u00e7ue selon la logique m\u00e9tier complexe du monolithe, et des liens se sont accumul\u00e9s entre les tables de diff\u00e9rents contextes limit\u00e9s.<\/p>\n<p>Dans notre cas, pour couronner le tout (grande base de donn\u00e9es, nombreux liens, fronti\u00e8res parfois floues entre les tables), nous avons rencontr\u00e9 un probl\u00e8me courant dans de nombreux grands projets : l'utilisation du mod\u00e8le de base de donn\u00e9es partag\u00e9e. Les donn\u00e9es \u00e9taient extraites des tables via des vues, r\u00e9pliqu\u00e9es et charg\u00e9es dans d'autres syst\u00e8mes o\u00f9 cette r\u00e9plique \u00e9tait n\u00e9cessaire. En cons\u00e9quence, nous ne pouvions pas d\u00e9placer les tables vers un sch\u00e9ma s\u00e9par\u00e9, car elles \u00e9taient activement utilis\u00e9es.<\/p>\n<p>La s\u00e9paration est facilit\u00e9e par ce d\u00e9coupage en contextes limit\u00e9s dans le code. Cela nous donne g\u00e9n\u00e9ralement une bonne id\u00e9e de la mani\u00e8re dont nous s\u00e9parons les donn\u00e9es au niveau de la base de donn\u00e9es. Nous comprenons quelles tables appartiennent \u00e0 un contexte limit\u00e9 et lesquelles en appartiennent \u00e0 un autre.<\/p>\n<p>Nous avons appliqu\u00e9 deux m\u00e9thodes globales de s\u00e9paration de base de donn\u00e9es : la s\u00e9paration des tables existantes et la s\u00e9paration avec refonte.<\/p>\n<p>La s\u00e9paration des tables existantes est une m\u00e9thode qui convient bien lorsque la structure des donn\u00e9es est de qualit\u00e9, r\u00e9pond aux exigences commerciales et satisfait tout le monde. Dans ce cas, nous pouvons extraire les tables existantes dans un sch\u00e9ma distinct.<\/p>\n<p>La s\u00e9paration avec refonte est n\u00e9cessaire lorsque le mod\u00e8le commercial a beaucoup chang\u00e9 et que les tables ne nous satisfont plus du tout.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"10\"><\/a><\/noindex><b>S\u00e9paration des tables existantes.<\/b> Nous devons d\u00e9terminer ce que nous allons s\u00e9parer. Sans cette connaissance, rien ne fonctionnera, et la s\u00e9paration des contextes limit\u00e9s dans le code nous aidera ici. En r\u00e8gle g\u00e9n\u00e9rale, si l'on peut comprendre les limites des contextes dans le code source, il devient clair quelles tables doivent figurer dans la liste \u00e0 s\u00e9parer.<\/p>\n<p>Imaginons que nous avons une solution dans laquelle deux modules d'un monolithe interagissent avec une seule base de donn\u00e9es. Nous devons faire en sorte qu'un module interagisse uniquement avec le segment de tables \u00e0 s\u00e9parer, tandis que l'autre commence \u00e0 interagir avec lui via une API. Pour commencer, il suffit que seules des \u00e9critures passent par l'API. C'est une condition n\u00e9cessaire pour que nous puissions parler de l'ind\u00e9pendance des microservices. Les relations en lecture peuvent rester tant qu'il n'y a pas de probl\u00e8me majeur.<\/p>\n<p><img decoding=\"async\" alt=\"Transition du monolithe vers les micros-services : histoire et pratique\" src=\"\/wp-content\/uploads\/2019\/07\/1602637ad752ac055f475cfa45d95e95.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nL'\u00e9tape suivante consiste \u00e0 extraire le segment de code qui travaille avec les tables \u00e0 s\u00e9parer, avec ou sans refonte, dans un microservice distinct et \u00e0 le lancer dans un processus ou un conteneur s\u00e9par\u00e9. Ce sera un service distinct avec une connexion \u00e0 la base de donn\u00e9es du monolithe et aux tables qui ne lui sont pas directement li\u00e9es. Le monolithe interagit encore en lecture avec la partie s\u00e9par\u00e9e. <\/p>\n<p><img decoding=\"async\" alt=\"Transition du monolithe vers les micros-services : histoire et pratique\" src=\"\/wp-content\/uploads\/2019\/07\/36011f4e6be4f6a2f19f2f074b645dcb.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nPlus tard, nous supprimerons cette connexion, ce qui signifie que la lecture des donn\u00e9es de l'application monolithique \u00e0 partir des tables s\u00e9par\u00e9es sera \u00e9galement transf\u00e9r\u00e9e vers l'API.<\/p>\n<p><img decoding=\"async\" alt=\"Transition du monolithe vers les micros-services : histoire et pratique\" src=\"\/wp-content\/uploads\/2019\/07\/290f91bbfccac2a4b384078e4cf4e337.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nEnsuite, nous extrairons des tables de la base de donn\u00e9es commune qui ne sont utilis\u00e9es que par le nouveau microservice. Nous pouvons d\u00e9placer les tables dans un sch\u00e9ma distinct ou m\u00eame dans une base de donn\u00e9es physique distincte. Il reste une relation en lecture entre le microservice et la base de donn\u00e9es du monolithe, mais cela n'est pas probl\u00e9matique ; dans cette configuration, il peut fonctionner encore longtemps.<\/p>\n<p><img decoding=\"async\" alt=\"Transition du monolithe vers les micros-services : histoire et pratique\" src=\"\/wp-content\/uploads\/2019\/07\/ab947ac6a38ffbccd4e2b51103aef609.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nLa derni\u00e8re \u00e9tape consiste \u00e0 \u00e9liminer compl\u00e8tement toutes les connexions. Dans ce cas, nous pourrions avoir besoin d'une migration des donn\u00e9es depuis la base de donn\u00e9es principale. Parfois, nous voudrons r\u00e9utiliser certaines donn\u00e9es ou r\u00e9pertoires r\u00e9pliqu\u00e9s de syst\u00e8mes externes dans plusieurs bases. Cela se produit p\u00e9riodiquement chez nous.<\/p>\n<p><img decoding=\"async\" alt=\"Transition du monolithe vers les micros-services : histoire et pratique\" src=\"\/wp-content\/uploads\/2019\/07\/f40cf17dd56b9575751e370c44f08344.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\n<noindex><a rel=\"nofollow\" name=\"11\"><\/a><\/noindex><b>Une section avec traitement.<\/b> Cette m\u00e9thode est tr\u00e8s similaire \u00e0 la premi\u00e8re, mais elle se d\u00e9roule dans l'ordre inverse. Nous cr\u00e9ons imm\u00e9diatement une nouvelle base de donn\u00e9es et un nouveau microservice qui interagit avec le monolithe via l'API. Cependant, il reste un ensemble de tables de la base de donn\u00e9es que nous souhaitons supprimer ult\u00e9rieurement. Nous n'en aurons plus besoin, dans le nouveau mod\u00e8le, nous l'avons remplac\u00e9.<\/p>\n<p><img decoding=\"async\" alt=\"Transition du monolithe vers les micros-services : histoire et pratique\" src=\"\/wp-content\/uploads\/2019\/07\/c94932033e47cfa1fd56595ab9a19246.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nPour que ce sch\u00e9ma fonctionne, nous aurons probablement besoin d'une p\u00e9riode de transition.<\/p>\n<p>Ensuite, il y a deux approches possibles.<\/p>\n<p><b>Premier<\/b>: nous dupliquons toutes les donn\u00e9es dans les nouvelles et anciennes bases. Dans ce cas, nous avons une redondance des donn\u00e9es, ce qui peut poser des probl\u00e8mes de synchronisation. Mais nous pouvons avoir deux clients diff\u00e9rents. L'un travaillera avec la nouvelle version, l'autre avec l'ancienne.<\/p>\n<p><b>Deuxi\u00e8me<\/b>: nous s\u00e9parons les donn\u00e9es selon un crit\u00e8re commercial. Par exemple, nous avions 5 produits dans le syst\u00e8me qui sont stock\u00e9s dans l'ancienne base de donn\u00e9es. Le sixi\u00e8me, dans le cadre de la nouvelle t\u00e2che commerciale, est plac\u00e9 dans la nouvelle base de donn\u00e9es. Cependant, nous allons avoir besoin d'une API Gateway qui synchronisera ces donn\u00e9es et indiquera au client d'o\u00f9 et quoi prendre.<\/p>\n<p>Les deux approches fonctionnent, choisissez en fonction de la situation.<\/p>\n<p>Apr\u00e8s avoir v\u00e9rifi\u00e9 que tout fonctionne, la partie du monolithe qui travaille avec les anciennes structures de la base de donn\u00e9es peut \u00eatre d\u00e9sactiv\u00e9e. <\/p>\n<p><img decoding=\"async\" alt=\"Transition du monolithe vers les micros-services : histoire et pratique\" src=\"\/wp-content\/uploads\/2019\/07\/973bf5015bdf49a290a5b901f89628cc.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nLa derni\u00e8re \u00e9tape consistera \u00e0 supprimer les anciennes structures de donn\u00e9es. <\/p>\n<p><img decoding=\"async\" alt=\"Transition du monolithe vers les micros-services : histoire et pratique\" src=\"\/wp-content\/uploads\/2019\/07\/fe83acc07077b7eb3717138e3c20c005.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nEn r\u00e9sum\u00e9, nous pouvons dire que nous avons des probl\u00e8mes avec la base de donn\u00e9es : il est difficile de travailler avec par rapport au code source, la s\u00e9paration est plus compliqu\u00e9e, mais cela peut et doit \u00eatre fait. Nous avons trouv\u00e9 certaines m\u00e9thodes qui permettent de le faire de mani\u00e8re relativement s\u00fbre, car il est plus facile de commettre une erreur avec les donn\u00e9es qu'avec le code source. <\/p>\n<p><noindex><a rel=\"nofollow\" name=\"12\"><\/a><\/noindex><b><\/p>\n<h3>Travail sur le code source<\/h3>\n<p><\/b><br \/>\nVoici \u00e0 quoi ressemblait le sch\u00e9ma du code source lorsque nous avons commenc\u00e9 \u00e0 analyser le projet monolithique.<\/p>\n<p><img decoding=\"async\" alt=\"Transition du monolithe vers les micros-services : histoire et pratique\" src=\"\/wp-content\/uploads\/2019\/07\/a6d886e37117ccf8f63106d6616aa653.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nElle peut \u00eatre divis\u00e9e conditionnellement en trois couches. Il s'agit de la couche des modules, plugins, services et activit\u00e9s ex\u00e9cutables. En fait, ce sont des points d'entr\u00e9e au sein d'une solution monolithique. Toutes \u00e9taient solidement reli\u00e9es par la couche Common. Elle contenait la logique m\u00e9tier utilis\u00e9e en commun par les services, et de nombreuses interconnexions. Chaque service et plugin utilisait jusqu'\u00e0 10 ensembles communs ou plus, selon leur taille et la conscience des d\u00e9veloppeurs.<\/p>\n<p>Nous avons eu de la chance, nous avions des biblioth\u00e8ques d'infrastructure qui pouvaient \u00eatre utilis\u00e9es s\u00e9par\u00e9ment. <\/p>\n<p>Il arrivait parfois que certains objets Common ne rel\u00e8vent en fait pas de cette couche, mais soient des biblioth\u00e8ques d'infrastructure. Cela \u00e9tait r\u00e9solu par un renommage.<\/p>\n<p>Les contextes limit\u00e9s ont suscit\u00e9 le plus de pr\u00e9occupations. Il arrivait que 3 \u00e0 4 contextes soient m\u00e9lang\u00e9s dans un m\u00eame ensemble Common et s'utilisent mutuellement dans le cadre des m\u00eames fonctions commerciales. Il \u00e9tait n\u00e9cessaire de comprendre o\u00f9 cela pouvait \u00eatre divis\u00e9 et selon quelles fronti\u00e8res, et quoi faire ensuite avec le mappage de cette division sur les ensembles de code source.<\/p>\n<p>Nous avons formul\u00e9 plusieurs r\u00e8gles pour le processus de s\u00e9paration du code.<\/p>\n<p><b>Premi\u00e8re<\/b>: nous ne souhaitions plus partager la logique m\u00e9tier entre les services, activit\u00e9s et plugins. Nous voulions rendre la logique m\u00e9tier ind\u00e9pendante dans le cadre des microservices. D'un autre c\u00f4t\u00e9, les microservices, dans l'id\u00e9al, sont per\u00e7us comme des services qui existent compl\u00e8tement ind\u00e9pendamment. Je pense que cette approche est quelque peu gaspill\u00e9e, et il est difficile de l'atteindre, car, par exemple, les services en C# seront de toute fa\u00e7on connect\u00e9s par la biblioth\u00e8que standard. Notre syst\u00e8me est \u00e9crit en C#, d'autres technologies n'ont pas encore \u00e9t\u00e9 utilis\u00e9es. Par cons\u00e9quent, nous avons d\u00e9cid\u00e9 que nous pouvions nous permettre d'utiliser des ensembles techniques communs. L'essentiel est qu'il n'y ait aucun fragment de logique m\u00e9tier dans ceux-ci. Si vous avez un wrapper pratique pour l'ORM que vous utilisez, alors le copier d'un service \u00e0 l'autre est tr\u00e8s co\u00fbteux.<\/p>\n<p>Notre \u00e9quipe est passionn\u00e9e par le design orient\u00e9 domaine, c'est pourquoi l'\u00ab architecture en oignon \u00bb nous convient parfaitement. La base de nos services n'est pas la couche d'acc\u00e8s aux donn\u00e9es, mais un assemblage avec la logique m\u00e9tier, qui contient uniquement la logique commerciale et est d\u00e9pourvue de liens avec l'infrastructure. Ainsi, nous pouvons am\u00e9liorer ind\u00e9pendamment l'assemblage de domaine pour r\u00e9soudre les probl\u00e8mes li\u00e9s aux frameworks.<\/p>\n<p>\u00c0 ce stade, nous avons rencontr\u00e9 notre premier probl\u00e8me majeur. Le service devait se r\u00e9f\u00e9rer \u00e0 un seul assemblage de domaine, la logique devant \u00eatre ind\u00e9pendante, et le principe DRY nous posait un r\u00e9el probl\u00e8me. Les d\u00e9veloppeurs souhaitaient \u00e9viter la duplication en r\u00e9utilisant des classes d'assemblages voisins, mais cela a entra\u00een\u00e9 un nouveau couplage entre les domaines. Nous avons analys\u00e9 les r\u00e9sultats et d\u00e9cid\u00e9 que le probl\u00e8me pouvait \u00e9galement r\u00e9sider dans la structure de stockage du code source. Nous avions un grand r\u00e9f\u00e9rentiel contenant tout le code source. Il \u00e9tait tr\u00e8s difficile de construire une Solution pour l'ensemble du projet sur une machine locale. Par cons\u00e9quent, des petites solutions s\u00e9par\u00e9es \u00e9taient cr\u00e9\u00e9es pour certaines parties du projet, et personne n'interdisait d'y ajouter un assemblage Common ou de domaine afin de le r\u00e9utiliser. Le seul outil qui nous emp\u00eachait de le faire \u00e9tait la revue de code. Mais parfois, m\u00eame cela \u00e9chouait.<\/p>\n<p>Nous avons donc commenc\u00e9 \u00e0 passer \u00e0 un mod\u00e8le avec des r\u00e9f\u00e9rentiels s\u00e9par\u00e9s. La logique m\u00e9tier a cess\u00e9 de fuir d'un service \u00e0 l'autre, et les domaines sont devenus v\u00e9ritablement ind\u00e9pendants. Les contextes limit\u00e9s sont maintenus de mani\u00e8re plus claire. Comment r\u00e9utilisons-nous les biblioth\u00e8ques d'infrastructure dans ce cas ? Nous les avons isol\u00e9es dans un r\u00e9f\u00e9rentiel distinct, puis plac\u00e9es dans des paquets Nuget, que nous avons ajout\u00e9s \u00e0 Artifactory. Pour toute modification, la construction et la publication se font automatiquement.<\/p>\n<p><img decoding=\"async\" alt=\"Transition du monolithe vers les micros-services : histoire et pratique\" src=\"\/wp-content\/uploads\/2019\/07\/8ddbc750dc7c6d397a459acf7825de90.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nNos services se r\u00e9f\u00e8rent d\u00e9sormais aux paquets d'infrastructure internes tout comme aux externes. Nous t\u00e9l\u00e9chargeons les biblioth\u00e8ques externes depuis Nuget. Pour travailler avec Artifactory, o\u00f9 nous stockions ces paquets, nous avons utilis\u00e9 deux gestionnaires de paquets. Dans les petits r\u00e9f\u00e9rentiels, nous avons \u00e9galement utilis\u00e9 Nuget. Dans les r\u00e9f\u00e9rentiels avec plusieurs services, nous avons utilis\u00e9 Paket, qui assure une meilleure coh\u00e9rence des versions entre les modules.<\/p>\n<p><img decoding=\"async\" alt=\"Transition du monolithe vers les micros-services : histoire et pratique\" src=\"\/wp-content\/uploads\/2019\/07\/672a25a70a481bff68baebe963184ccd.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nAinsi, en travaillant sur le code source, en modifiant l\u00e9g\u00e8rement l'architecture et en divisant les d\u00e9p\u00f4ts, nous rendons nos services plus ind\u00e9pendants.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"13\"><\/a><\/noindex><b><\/p>\n<h3>Probl\u00e8mes d'infrastructure<\/h3>\n<p><\/b><br \/>\nLa plupart des inconv\u00e9nients li\u00e9s \u00e0 la transition vers les microservices sont associ\u00e9s \u00e0 l'infrastructure. Vous aurez besoin d'un d\u00e9ploiement automatis\u00e9 et de nouvelles biblioth\u00e8ques pour g\u00e9rer l'infrastructure.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"16\"><\/a><\/noindex><b>Installation manuelle dans les environnements<\/b><\/p>\n<p>\u00c0 l'origine, nous installions les solutions d'environnement \u00e0 la main. Pour automatiser ce processus, nous avons cr\u00e9\u00e9 un pipeline CI\/CD. Nous avons opt\u00e9 pour un processus de livraison continue, car le d\u00e9ploiement continu est encore inacceptable du point de vue des processus commerciaux. Ainsi, le d\u00e9ploiement en production se fait par un bouton, tandis que les tests sont automatis\u00e9s.<\/p>\n<p><img decoding=\"async\" alt=\"Transition du monolithe vers les micros-services : histoire et pratique\" src=\"\/wp-content\/uploads\/2019\/07\/0fc092326a48813398c6f3a031197bab.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nNous utilisons Atlassian, Bitbucket pour le stockage des codes sources et Bamboo pour la compilation. Nous aimons \u00e9crire des scripts de compilation en Cake, car c'est le m\u00eame langage que C#. Les paquets arrivent pr\u00eats dans Artifactory, et Ansible les d\u00e9ploie automatiquement sur les serveurs de test, o\u00f9 ils peuvent ensuite \u00eatre test\u00e9s imm\u00e9diatement.<\/p>\n<p><img decoding=\"async\" alt=\"Transition du monolithe vers les micros-services : histoire et pratique\" src=\"\/wp-content\/uploads\/2019\/07\/fcc743cfaa4a24b906ceeb40ec1ba0a0.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\n<noindex><a rel=\"nofollow\" name=\"14\"><\/a><\/noindex><b><\/p>\n<h3>Journalisation s\u00e9par\u00e9e<\/h3>\n<p><\/b><br \/>\n\u00c0 l'\u00e9poque, l'une des id\u00e9es du monolithe \u00e9tait de garantir une journalisation conjointe. Nous devions \u00e9galement comprendre comment g\u00e9rer les journaux s\u00e9par\u00e9s qui se trouvent sur les disques. Nos journaux sont \u00e9crits dans des fichiers texte. Nous avons d\u00e9cid\u00e9 d'utiliser la pile ELK standard. Nous n'avons pas \u00e9crit directement dans ELK via des fournisseurs, mais avons convenu de peaufiner les journaux texte et d'y enregistrer les ID de tra\u00e7age sous forme d'identifiant, en ajoutant le nom du service, afin que ces journaux puissent ensuite \u00eatre analys\u00e9s.<\/p>\n<p><img decoding=\"async\" alt=\"Transition du monolithe vers les micros-services : histoire et pratique\" src=\"\/wp-content\/uploads\/2019\/07\/8e58c66ac134e65abe34b59939f31483.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nAvec Filebeat, nous avons la possibilit\u00e9 de collecter nos journaux de <a class=\"wpil_keyword_link\" href=\"https:\/\/prohoster.info\/fr\/server\/\"   title=\"serveurs\" data-wpil-keyword-link=\"linked\"  data-wpil-monitor-id=\"1338\">serveurs<\/a>, puis de les transformer, d'utiliser Kibana pour construire des requ\u00eates dans l'interface utilisateur et de voir comment les appels se sont d\u00e9roul\u00e9s entre les services. Cela est grandement facilit\u00e9 par l'ID de tra\u00e7age.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"15\"><\/a><\/noindex><b><\/p>\n<h3>Tests et d\u00e9bogage des services interconnect\u00e9s<\/h3>\n<p><\/b><br \/>\nAu d\u00e9part, nous ne comprenions pas compl\u00e8tement comment d\u00e9boguer les services que nous d\u00e9veloppions. Avec le module monolithique, c'\u00e9tait simple, nous le lancions sur notre machine locale. Nous avons d'abord essay\u00e9 de faire de m\u00eame avec les microservices, mais parfois, pour ex\u00e9cuter pleinement un microservice, il faut \u00e9galement lancer plusieurs autres, ce qui s'av\u00e8re peu pratique. Nous avons compris qu'il \u00e9tait n\u00e9cessaire de passer \u00e0 un mod\u00e8le o\u00f9 nous laissons sur la machine locale uniquement le service ou les services que nous souhaitons d\u00e9boguer. Les autres services sont utilis\u00e9s \u00e0 partir de serveurs ayant la m\u00eame configuration que la production. Apr\u00e8s d\u00e9bogage, lors des tests, seuls les services modifi\u00e9s sont d\u00e9ploy\u00e9s sur le serveur de test pour chaque t\u00e2che. Ainsi, la solution est test\u00e9e dans l'\u00e9tat o\u00f9 elle se trouvera \u00e0 l'avenir en production.<\/p>\n<p>Il existe des serveurs sur lesquels ne se trouvent que les versions de production des services. Ces serveurs sont n\u00e9cessaires en cas d'incidents, pour v\u00e9rifier la livraison avant le d\u00e9ploiement et pour des formations internes.<\/p>\n<p>Nous avons ajout\u00e9 un processus de test automatique en utilisant la biblioth\u00e8que populaire Specflow. Les tests sont lanc\u00e9s automatiquement via NUnit imm\u00e9diatement apr\u00e8s le d\u00e9ploiement \u00e0 partir d'Ansible. Si la couverture de la t\u00e2che est enti\u00e8rement automatis\u00e9e, il n'est pas n\u00e9cessaire de faire des tests manuels. Cependant, il arrive parfois qu'un test manuel suppl\u00e9mentaire soit n\u00e9cessaire. Pour d\u00e9terminer quels tests ex\u00e9cuter pour une t\u00e2che sp\u00e9cifique, nous utilisons des tags dans Jira.<\/p>\n<p>De plus, le besoin de tests de charge a augment\u00e9, auparavant ils n'\u00e9taient r\u00e9alis\u00e9s que dans de rares cas. Pour lancer les tests, nous utilisons JMeter, pour leur stockage \u2014 InfluxDB, et pour la cr\u00e9ation de graphiques du processus \u2014 Grafana.<\/p>\n<p><b><\/p>\n<h3>Qu'avons-nous accompli ?<\/h3>\n<p><\/b><br \/>\nTout d'abord, nous nous sommes d\u00e9barrass\u00e9s du concept de 'release'. Les \u00e9normes releases de deux mois ont disparu, lorsque ce mastodonte \u00e9tait d\u00e9ploy\u00e9 en environnement de production, perturbant temporairement les processus m\u00e9tiers. Aujourd'hui, nous d\u00e9ployons les services en moyenne tous les 1,5 jours, en les regroupant, car ils entrent en production apr\u00e8s accord.<\/p>\n<p>Dans notre syst\u00e8me, il n'y a pas de pannes fatales. Si nous publions un microservice avec une erreur, alors la fonctionnalit\u00e9 associ\u00e9e sera d\u00e9faillante, mais toutes les autres fonctionnalit\u00e9s ne seront pas affect\u00e9es. Cela am\u00e9liore consid\u00e9rablement l'exp\u00e9rience utilisateur.<\/p>\n<p>Nous pouvons g\u00e9rer le sch\u00e9ma de d\u00e9ploiement. Il est possible de distinguer des groupes de services s\u00e9par\u00e9ment du reste de la solution, si n\u00e9cessaire.<\/p>\n<p>De plus, nous avons consid\u00e9rablement r\u00e9duit le probl\u00e8me des longues files d'attente de modifications. Nous avons constitu\u00e9 des \u00e9quipes produits distinctes qui travaillent avec une partie des services de mani\u00e8re autonome. Ici, le processus Scrum fonctionne d\u00e9j\u00e0 assez bien. Une \u00e9quipe sp\u00e9cifique peut avoir un propri\u00e9taire de produit distinct qui lui fixe des t\u00e2ches. <\/p>\n<p><b><\/p>\n<h3>R\u00e9sum\u00e9<\/h3>\n<p><\/b><\/p>\n<ul>\n<li>Les microservices sont bien adapt\u00e9s pour la d\u00e9composition de syst\u00e8mes complexes. Au cours du processus, nous commen\u00e7ons \u00e0 comprendre ce qu'il y a dans notre syst\u00e8me, quels contextes restreints existent et o\u00f9 se trouvent leurs fronti\u00e8res. Cela permet de r\u00e9partir correctement les modifications entre les modules et d'\u00e9viter de rendre le code confus. <\/li>\n<li>Les microservices offrent des avantages organisationnels. On en parle souvent uniquement en tant qu'architecture, mais toute architecture existe pour r\u00e9pondre aux besoins de l'entreprise, et non pour elle-m\u00eame. Par cons\u00e9quent, nous pouvons dire que les microservices sont bien adapt\u00e9s aux t\u00e2ches effectu\u00e9es par de petites \u00e9quipes, \u00e9tant donn\u00e9 que Scrum est tr\u00e8s populaire actuellement.<\/li>\n<li>La s\u00e9paration est un processus it\u00e9ratif. On ne peut pas simplement prendre une application et la diviser en microservices. Le produit r\u00e9sultant sera probablement non fonctionnel. Lors de l'extraction de microservices, il est avantageux de r\u00e9\u00e9crire l'ancien code existant, c'est-\u00e0-dire de le transformer en code qui nous pla\u00eet et qui r\u00e9pond mieux aux besoins de l'entreprise en termes de fonctionnalit\u00e9s et de rapidit\u00e9.\n<p><i>Une petite mise en garde :<\/i> les co\u00fbts de transition vers les microservices sont suffisamment importants. Beaucoup de temps a \u00e9t\u00e9 consacr\u00e9 \u00e0 r\u00e9soudre les probl\u00e8mes d'infrastructure. Par cons\u00e9quent, si vous avez une petite application qui ne n\u00e9cessite pas de mise \u00e0 l'\u00e9chelle sp\u00e9cifique, si vous n'avez pas un grand nombre de clients luttant pour l'attention et le temps de votre \u00e9quipe, alors peut-\u00eatre que les microservices ne sont pas ce dont vous avez besoin aujourd'hui. C'est assez cher. Si vous commencez le processus avec des microservices, les co\u00fbts initiaux seront plus \u00e9lev\u00e9s que si le m\u00eame projet \u00e9tait d\u00e9marr\u00e9 avec le d\u00e9veloppement d'un monolithe. <\/p>\n<p>P.S. Une narration plus \u00e9motionnelle (comme si cela vous concernait personnellement) - \u00e0 propos de <noindex><a rel=\"nofollow\" href=\"https:\/\/www.youtube.com\/watch?v=qTNbx18DzpQ\">le lien<\/a><\/noindex>. <br \/>\nVoici la version compl\u00e8te de la pr\u00e9sentation.<\/li>\n<\/ul>\n<p>Source : <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/raiffeisenbank\/blog\/458404\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u043f\u0440\u043e\u0435\u043a\u0442, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u044f \u0440\u0430\u0431\u043e\u0442\u0430\u044e, \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u043b\u0441\u044f \u0438\u0437 \u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u043c\u043e\u043d\u043e\u043b\u0438\u0442\u0430 \u0432 \u043d\u0430\u0431\u043e\u0440 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432. \u041f\u0440\u043e\u0435\u043a\u0442 \u043d\u0430\u0447\u0430\u043b \u0441\u0432\u043e\u044e \u0438\u0441\u0442\u043e\u0440\u0438\u044e \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0434\u0430\u0432\u043d\u043e, \u0432 \u043d\u0430\u0447\u0430\u043b\u0435 2000. \u041f\u0435\u0440\u0432\u044b\u0435 \u0432\u0435\u0440\u0441\u0438\u0438 \u0431\u044b\u043b\u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u044b \u043d\u0430 Visual Basic 6. \u0421 \u0442\u0435\u0447\u0435\u043d\u0438\u0435\u043c \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0441\u0442\u0430\u043b\u043e \u043f\u043e\u043d\u044f\u0442\u043d\u043e, \u0447\u0442\u043e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u043d\u0430 \u044d\u0442\u043e\u043c \u044f\u0437\u044b\u043a\u0435 \u0432 \u0431\u0443\u0434\u0443\u0449\u0435\u043c \u0431\u0443\u0434\u0435\u0442 \u0441\u043b\u043e\u0436\u043d\u043e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c, \u0442\u0430\u043a \u043a\u0430\u043a IDE [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":26858,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-35906","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.2 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u043f\u0440\u043e\u0435\u043a\u0442, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u044f \u0440\u0430\u0431\u043e\u0442\u0430\u044e, \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u043b\u0441\u044f \u0438\u0437 \u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u043c\u043e\u043d\u043e\u043b\u0438\u0442\u0430 \u0432 \u043d\u0430\u0431\u043e\u0440 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432. \u041f\u0440\u043e\u0435\u043a\u0442 \u043d\u0430\u0447\u0430\u043b \u0441\u0432\u043e\u044e \u0438\u0441\u0442\u043e\u0440\u0438\u044e \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0434\u0430\u0432\u043d\u043e, \u0432 \u043d\u0430\u0447\u0430\u043b\u0435 2000.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/fr\/blog\/administrirovanie\/perehod-ot-monolita-k-mikroservisam-istoriya-i-praktika\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.2\" \/>\n\t\t<meta property=\"og:locale\" content=\"fr_FR\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u041f\u0435\u0440\u0435\u0445\u043e\u0434 \u043e\u0442 \u043c\u043e\u043d\u043e\u043b\u0438\u0442\u0430 \u043a \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u0430\u043c: \u0438\u0441\u0442\u043e\u0440\u0438\u044f \u0438 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0430 | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u043f\u0440\u043e\u0435\u043a\u0442, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u044f \u0440\u0430\u0431\u043e\u0442\u0430\u044e, \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u043b\u0441\u044f \u0438\u0437 \u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u043c\u043e\u043d\u043e\u043b\u0438\u0442\u0430 \u0432 \u043d\u0430\u0431\u043e\u0440 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432. \u041f\u0440\u043e\u0435\u043a\u0442 \u043d\u0430\u0447\u0430\u043b \u0441\u0432\u043e\u044e \u0438\u0441\u0442\u043e\u0440\u0438\u044e \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0434\u0430\u0432\u043d\u043e, \u0432 \u043d\u0430\u0447\u0430\u043b\u0435 2000.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/fr\/blog\/administrirovanie\/perehod-ot-monolita-k-mikroservisam-istoriya-i-praktika\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-10-31T19:07:29+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2019-10-31T19:07:29+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47La transition du monolithe aux microservices : histoire et pratique | ProHoster","description":"Dans cet article, je vais vous parler de la mani\u00e8re dont le projet sur lequel je travaille s'est transform\u00e9 d'un grand monolithe en une s\u00e9rie de microservices. Le projet a commenc\u00e9 son histoire il y a d\u00e9j\u00e0 quelque temps, au d\u00e9but des ann\u00e9es 2000.","canonical_url":"https:\/\/prohoster.info\/fr\/blog\/administrirovanie\/perehod-ot-monolita-k-mikroservisam-istoriya-i-praktika","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"fr_FR","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u041f\u0435\u0440\u0435\u0445\u043e\u0434 \u043e\u0442 \u043c\u043e\u043d\u043e\u043b\u0438\u0442\u0430 \u043a \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u0430\u043c: \u0438\u0441\u0442\u043e\u0440\u0438\u044f \u0438 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0430 | ProHoster","og:description":"\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u043f\u0440\u043e\u0435\u043a\u0442, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u044f \u0440\u0430\u0431\u043e\u0442\u0430\u044e, \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u043b\u0441\u044f \u0438\u0437 \u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u043c\u043e\u043d\u043e\u043b\u0438\u0442\u0430 \u0432 \u043d\u0430\u0431\u043e\u0440 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432. \u041f\u0440\u043e\u0435\u043a\u0442 \u043d\u0430\u0447\u0430\u043b \u0441\u0432\u043e\u044e \u0438\u0441\u0442\u043e\u0440\u0438\u044e \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0434\u0430\u0432\u043d\u043e, \u0432 \u043d\u0430\u0447\u0430\u043b\u0435 2000.","og:url":"https:\/\/prohoster.info\/fr\/blog\/administrirovanie\/perehod-ot-monolita-k-mikroservisam-istoriya-i-praktika","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2019-10-31T19:07:29+00:00","article:modified_time":"2019-10-31T19:07:29+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"35906","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-02-09 17:04:56","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-03-01 01:54:38","updated":"2026-02-09 17:04:56","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/posts\/35906","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/comments?post=35906"}],"version-history":[{"count":1,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/posts\/35906\/revisions"}],"predecessor-version":[{"id":158582,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/posts\/35906\/revisions\/158582"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/media\/26858"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/media?parent=35906"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/categories?post=35906"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/tags?post=35906"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}