API monolithique vers micro services [ALTERNANCE]

Le problème exposé dans ce sujet a été résolu.

J’ai une alternance pour deux ans, le patron veut que je commence rapidement par ce que :

  • Il y a deux alternants qui gère l’ensemble de la partie "informatique" de la boite, les deux alternants ont fait (sur conseil de leurs prof) une API monolithique en C#, cette dites API est fais avec ASP.NET (pas core), elle tourne sur Windows Server 2016 et Azure devops

Ils ont des problèmes monstrueux, (l’app qui crash aléatoirement, grosse consommation de ressource, le prix des licences de windows server)

Ma première mission consiste avec l’aide d’un autre alternant de refaire cette API sans les problèmes actuel,

Les deux alternants m’ont conseillé d’éclaté le tout en micro service et de changer la stack

L’API gère pas mal de chose comme le site web, l’intra, etc … et elle fais bcp de grosse tâche, genre modification d’image, génération de pdf (d’ailleurs il paie un module par ce qu’ils en ont pas trouvé d’open source gratuit en C# pour sa)

J’ai deux questions :

  • Quel stack
  • Comment m’y prendre pour éclater le tout en micro service en partant d’une grosse API monolithique

Merci d’avance

Bonjour,

Il faudrait déjà savoir sur quel langage tu comptes partir ? Personnellement, je partirai sur du Node.js. On trouve sans problème des modules de cron, génération de PDF et cie. Toutefois, ça veut dire repartir de zéro. Est-ce que ton patron est prêt à investir là-dessus ? pas sûr. Sachant que la mise en place d’une stack peut prendre déjà du temps.

Ensuite les micro-services, tu peux utiliser des outils comme Docker pour avoir une isolation par service. Il te faut découper les ensembles métiers qui ont lieu au sein de ton application : partie client (site web), partie serveur de données, stockage, intranet etc. L’avantage de Docker c’est qu’il peut relancer automatiquement les services qui sont tombés. A l’usage, tu n’as pratiquement rien à gérer. Juste à checker les logs de temps en temps.

Le découpage en micro-services peut se faire dans un dépôt GIT avec plusieurs sous-répertoires et une configuration de montage (un fichier docker-compose et des dockerfile).

J’avoue être assez allergique aux technos Windows donc je ne peux pas t’affirmer qu’une application ASP.net tournera bien sur Docker. Il vaudrait sûrement mieux utiliser leurs outils en ligne avec la console .NET (attention ça peut coûter cher à héberger).

Edit : après créer une API tentaculaires c’est effectivement pas l’idée du siècle, tu pourrais à la limite décharger une partie de l’API en la splitant dans les différents services, ceux concernés par les tâches et les appeler depuis une entrée bien définie (pattern en façade).

+0 -0

Le premier point qui me fait bondir c’est pourquoi une entreprise confie la gestion de son informatique à deux alternants sans avoir un salarié pour gérer et prendre ce genre de décisions ? C’est pas à des juniors d’être responsable de l’architecture technique, vous êtes là pour apprendre, pas prendre de telles responsabilités !

Ensuite il faudrait voir les technos que l’entreprise sait et peut maintenir. Utiliser Node.js ça peut être sympa, mais si personne peut maintenir le projet après votre alternance ce sera retour à zéro pour re-développer tout ça.

Ensuite Docker ou pas en soit c’est pas le moment de vous poser la question. On peut très bien faire du micro-services sans Docker, comme on peut faire du monolithique avec.

Les problèmes actuels sont là, soit, mais ont-ils été analysés par un professionnels avant de décider de tout refaire ?

Toutefois, ça veut dire repartir de zéro. Est-ce que ton patron est prêt à investir là-dessus ?

Il est d’accord puisque c’est lui qui le souhaite.

Avec la console .NET (attention ça peut coûter cher à héberger

C’est justement la raison qui pousse aussi le patron à vouloir changer de stack

pourquoi une entreprise confie la gestion de son informatique à deux alternants sans avoir un salarié pour gérer et prendre ce genre de décisions ?

Je suis bien d’accord mais apparemment pas eux…

Ensuite il faudrait voir les technos que l’entreprise sait et peut maintenir.

Outre moi, personne n’est dans le service informatique, donc après mon alternance, ça sera au prochain alternant d’apprendre la stack et la faire évoluer

Les problèmes actuels sont là, soit, mais ont-ils été analysés par un professionnels avant de décider de tout refaire ?

Non justement, c’est à moi de me débrouiller avec l’aide mon compagnon de guerre, d’où ma demande sur ce forum

Le premier point qui me fait bondir c’est pourquoi une entreprise confie la gestion de son informatique à deux alternants sans avoir un salarié pour gérer et prendre ce genre de décisions ? C’est pas à des juniors d’être responsable de l’architecture technique, vous êtes là pour apprendre, pas prendre de telles responsabilités !

Malheureusement c’est le problème de beaucoup d’entreprises : travailler à moindre coût. Entre payer un ingénieur à 40k€ brut et un alternant au SMIC … la formation étant réduire en grande partie par les OPCA. Y’a pas photo. On est d’accord c’est débile mais …. c’est comme ça. Faut arrêter d’idéaliser le travail, y’a aussi une réalité économique. Rien que mes patrons ont mis fin à 3 contrats en alternance ce mois-ci dans la boîte, merci le Covid-19 et les aides de l’état pour que les jeunes puissent avoir leurs chances. Bref, je ne vais pas débattre. C’est compliqué et cette situation ne me plaît pas particulièrement.

Bon courage pour ton travail Qarasina, penses à la doc et à structurer tes idées - c’est le plus important. :)

Vous me conseillez tous Node.JS et j’en suis assez ravis, je l’ai proposé à l’autre alternant qui vient de me répondre :

"tu peux faire de la concurrence mais pas du multithread c’est de la merde pour le back parce que: 1 - c’est interprété 2 - plus gourmand en mémoire 3 - pas scalable 4 - lent"

J’ai l’impression qu’il sera dur à convaincre mais je trouve qu’il a tord sur tout les points :

0 - tu peux faire de la concurrence mais pas du multithread, d’accord sauf que le multi thread, c’est loin d’être intéressant aujourd’hui puisqu’on sait que les codes multi thread ont une tonne de problème, maintenant on préfère le multi thread à forte isolation (ex: Workers) ou bien le multi processus

1 - Oui, interprété mais en quoi c’est mal ?

2 - Source ? J’en ai jamais entendu parler, ni vu de gens s’en plaindre (par rapport à la JVM)

3 - Pas scalable, c’est surtout le code qui est ou non scalable pas le runtime

4 - lent ? J’ai entendu beaucoup d’écho venant du Fortune 500 et des "licornes" dire que Node était justement bien plus rapide que Java EE dans bien des scénarios

Je ne sais pas si je me trompe ?

+0 -0

0 - Ça ne permet pas du multithread

On peut mais ce n’est pas la philosophie, on utilise plutôt des fonctions asynchrones pour paralléliser les tâches. Le multithread s’apparenterait plutôt à ta grappe de micro-services Node.

1 - C’est interprété

Il faut savoir que le moteur V8 optimise la consommation de la mémoire et le nettoyage avec le GC. Puis pour la partie réseau notamment, ça utilise des librairies compilés.

2 - Plus gourmand en mémoire

Ça dépend par rapport à quoi ? La techno .NET à côté n’est pas moins gourmande … c’est le moins qu’on puisse dire ah ah. :p

3 - Pas scalable

Ça se discute, tout dépend de la stack. Pour un jeu en ligne multi avec des rooms, tu peux très bien dupliquer tes instances sans aucun problème. C’est pas vraiment une histoire de langage même si certains ont des outils plus efficaces que d’autres.

4 - Lent

C’est vague. Ça dépend des usages. Par rapport à J2EE, je ne sais pas. Il faut aussi prendre en compte les capacités du serveur. Java restera toujours plus gourmand à faire tourner que du JS mais la montée en charge ne sera pas forcément la même.

+0 -0

Très franchement, si l’API est foutue correctement, que ce soit du Node ou du Java ou du Go ou quoi que ce soit d’autre aura relativement peu d’incidence. Par exemple un seul conteneur Go qui sert un de tes services pourra certainement encaisser dix fois plus de charge qu’un conteneur Node qui fait le même boulot, mais si ton API est pensée pour que les conteneurs eux-mêmes soient scalés, tu t’en fous un peu.

Le plus important ça va être de documenter, tester, instrumenter tout ce projet pour qu’il reste manageable. Toutes les stacks modernes permettent de faire ça. Le reste n’est qu’une question de goût : partez sur le truc qui vous branche le plus et sur lequel vous vous sentez bien.

+2 -0

Par exemple un seul conteneur Go qui sert un de tes services pourra certainement encaisser dix fois plus de charge qu’un conteneur Node qui fait le même boulot

Pourquoi ? @nohar

Le plus important ça va être de documenter, tester, instrumenter tout ce projet pour qu’il reste manageable. Toutes les stacks modernes permettent de faire ça. Le reste n’est qu’une question de goût : partez sur le truc qui vous branche le plus et sur lequel vous vous sentez bien.

Je vais essayer de le garder en tête, mais bon c’est pas évident sans lead tech de devoir prendre des décisions qui vont impacter une entreprise entière

+0 -0

Oui avec des beaux graphiques :) : https://medium.com/javarevisited/node-js-vs-java-why-compare-b3e19b11cd55.

Yarflam

Et plein de problèmes et d’affirmations douteuses dans les deux cas (notamment le comparatif du nombre de paquets et du rythme de sortie des versions), et aucune source et rien de reproductible, hélas. Je vais donc me permettre de douter de cette réalité et de rester dubitatif.

(Cela dit, en 2020 sur des programmes bien développés, les cas où tu as réellement un problème de performances à cause de ton langage devrait rester bien marginal).

Et plein de problèmes et d’affirmations douteuses dans les deux cas (notamment le comparatif du nombre de paquets et du rythme de sortie des versions), et aucune source et rien de reproductible, hélas. Je vais donc me permettre de douter de cette réalité et de rester dubitatif.

J’aurais bien envie d’ajouter qu’en plus l’article est hosté sur Medium, ce qui, à titre personnel, le place automatiquement tout en bas de mon échelle de confiance en ce qui concerne les publications techniques.

+2 -0

Vous me conseillez tous Node.JS et j’en suis assez ravis, je l’ai proposé à l’autre alternant qui vient de me répondre :

"tu peux faire de la concurrence mais pas du multithread c’est de la merde pour le back parce que: 1 - c’est interprété 2 - plus gourmand en mémoire 3 - pas scalable 4 - lent"

J’ai l’impression qu’il sera dur à convaincre mais je trouve qu’il a tord sur tout les points :

0 - tu peux faire de la concurrence mais pas du multithread, d’accord sauf que le multi thread, c’est loin d’être intéressant aujourd’hui puisqu’on sait que les codes multi thread ont une tonne de problème, maintenant on préfère le multi thread à forte isolation (ex: Workers) ou bien le multi processus

1 - Oui, interprété mais en quoi c’est mal ?

2 - Source ? J’en ai jamais entendu parler, ni vu de gens s’en plaindre (par rapport à la JVM)

3 - Pas scalable, c’est surtout le code qui est ou non scalable pas le runtime

4 - lent ? J’ai entendu beaucoup d’écho venant du Fortune 500 et des "licornes" dire que Node était justement bien plus rapide que Java EE dans bien des scénarios

Je ne sais pas si je me trompe ?

Qarasina

La bonne question n’est pas de savoir si tu trompes. La bonne question c’est : et alors ? Est-ce que ces détails techniques ont une importance pour le projet ? Si oui, lesquels et pourquoi ?

Pro tip de «senior » (puisque vous devez agir en tant que tel de toute façon) : posez des questions et débattez sur les besoins du projets, et utilisez simplement le langage que tout le monde connaît déjà (même juste un peu) pour ne pas perdre du temps et de l’énergie inutilement.

+2 -0

J’avais pas vu cette question :

Par exemple un seul conteneur Go qui sert un de tes services pourra certainement encaisser dix fois plus de charge qu’un conteneur Node qui fait le même boulot

Pourquoi ? @nohar

Qarasina

Parce que Go est littéralement fait pour ça et utilise un modèle de concurrence qui permet à un seul processus de meubler tous les CPU que tu lui autorises à utiliser. On parle de concurrence N:M : sur N threads (N étant le nombre de CPU à dispo), Go va orchestrer M goroutines concurrentes, N pouvant monter jusqu’à 32 sur des vraiment gros serveurs, et M étant facilement de l’ordre de 10000 sans broncher. Là, on est typiquement dans les considérations "telle techno est nativement 'plus rapide' que telle autre". Mais comme je l’ai dit plus haut, dans la réalité ces considérations sont secondaires et ne commencent à prendre de l’importance quand tu en es à vouloir garantir les performances de ton API "au 99e pourcentile". Autant dire que ces questions n’ont, là tout de suite, aucune importance pour toi, parce qu’avant de se les poser, il va falloir déjà que tu aies ton API sous la forme de microservices, documentée, déployée, monitorée et testée. C’est seulement quand tu as un backend qui fait vraiment bien le job de façon qualitative que tu devras peut-être envisager remplacer tel ou tel microservice par quelque chose de plus performant.

Du coup on en revient à ce que je disais : d’abord, partez sur une techno qui vous plait et avec laquelle vous êtes à l’aise. Si c’est Node, partez sur Node. Si c’est Java ou Kotlin, partez sur Java ou Kotlin. Il est vraiment capital de faire sauter l’idée reçue qui voudrait qu’un choix technique va vous marier à une stack à vie : tout l’intérêt des microservices est justement de pouvoir jeter et refaire un service à moindre coût quand il y en a besoin.

+3 -0

Tout d’abord, merci pour vos réponses

@nohar, je me permet de répondre à ton message de manière rapide, j’ai repris en considération l’ensemble des besoins de l’entreprise et j’en suis arrivé à un conclusion relativement simple :

Refaire l’api en micro services avec Go, cette conclusion est arrivée après avoir fais un simple "état des lieux",

J’hésitais grandement entre Scala (qui je trouve est un langage riche et très intéressant tout en ayant une approche très "robuste") et Go justement

J’ai finis par me dire simplement que j’étais un alternant qui allait travaillé avec un autre alternant (dont je ne connais pas le niveau) et qu’ainsi il serait risqué de vouloir partir sur un langage aussi complexe et théorique que Scala, de plus, les machines dont nous disposons ne sont clairement pas très puissante, (on parle de 2gb ram), donc je doute qu’une JVM puisse exploiter son maximum à l’inverse de Go

Je vous remercies pour vos retours qui m’ont permis de prendre cette décision et de m’en tenir

Go est un excellent choix, y compris pour démarrer un projet, et particulièrement si l’un de tes objectifs est de moderniser ta stack.

Je me suis retenu de te pousser explicitement vers lui parce que je ne suis pas objectif sur le sujet : c’est le langage avec lequel je bosse depuis des mois, sur le backend d’un MMORPG, et je m’éclate comme un petit fou avec. Mais par défaut c’est effectivement le langage que j’aurais choisi parce qu’il excelle dans ce domaine, en plus d’être vraiment facile à prendre en main : c’est pas évident de trouver des ingés qui ont une expérience en Go, mais ça ne coûte pratiquement rien de former des ingés qui ont de l’expérience, à utiliser Go.

Pour le coup, si tu es fixé dessus et que tu as des questions sur le reste de la stack, n’hésite pas. J’ai dû moi-même pas mal explorer l’écosystème ces derniers mois.

+0 -0

J’aimerai beaucoup avoir le lien vers le github du back-end du MMORPG

C’est un projet pro, il est privé…

J’aimerai également que tu me conseilles un framework si tu en connais un bon pour mon besoin

Qarasina

Alors il faut savoir que le terme framework est assez peu populaire chez les devs Go : il existe bien des frameworks web MVC comme Buffalo par exemple, qui sont pas mal pour réaliser des sites ou même des API à moindre effort, mais on préfère généralement utiliser des bibliothèques indépendantes les unes des autres, chacune faisant le job dont on a besoin.

Voilà un petit retour sur la stack de mon projet actuel si tu veux :

  • Mon API n’est pas du REST/json classique : j’ai plutôt opté directement pour grpc. L’avantage immense que ça a (au-delà des perfs ou autres), c’est qu’en bossant avec GRPC, tu commences par définir une spec qui décrit tes services de façon déclarative : quel service fait quoi, quelle tête ont les messages. Ça n’en a pas l’air, mais commencer par là est un excellent moyen de communication entre les devs ou équipes de devs chargés de réaliser les différents services, parce que ça impose (et permet) de se mettre d’accord sur le "contrat" du service. Et partant de cette spec, tu vas pouvoir générer automatiquement le client pour ce service dans n’importe quel langage courant, ainsi qu’un stub pour ton serveur (en gros, tu n’as plus qu’à coder les méthodes concrètes).
  • Si pour une raison technique, tu as besoin de communiquer avec un service gRPC mais à partir d’un client qui n’a pas du tout la possibilité d’utiliser ta bibliothèque générée, tu peux toujours placer tes services derrière une gateway qui va les exposer derrière du REST/JSON/HTTP classique (https://github.com/grpc-ecosystem/grpc-gateway).
  • On utilise plusieurs bases de données. Typiquement, du Postgre et du MongoDB. Pour la base SQL, j’utitilise gorm. C’est l’ORM le plus populaire en Go. Petit combo bonus : il existe un tool développé par atlassian, protoc-gen-gorm, qui te permet de faire encore plus la faignasse avec GRPC : il va générer les modèles GORM pour toi à partir de ta spec grpc, et quand tu veux simplement exposer un service avec des opérations CURLD (Create Update, Read, List, Delete) classiques sur ton modèle, celui-ci va t’auto-générer tout le code de ces méthodes, et te laisser le loisir de l'overrider à ta guise au besoin : généralement, le comportement par défaut suffit. Ça fait toujours moins de code à tester explicitement, puisque c’est du code généré.
  • Pour les migrations de base de données SQL, j’utilise migrate, que tu peux utiliser aussi bien en CLI que sous forme de bibliothèque que tu intègres à ton service. Perso, j’ai opté pour cette seconde option.
  • Les fichiers de migration sont compilés en statique dans mon binaire grâce à bindata.
  • Pour gérer à la fois la ligne de commande (ex. api serve, api migrate…) de mes services, ainsi que leur configuration, j’utilise les incontournables cobra et viper, qui sont faits pour fonctionner ensemble, et t’imposent immédiatement de bonnes pratiques (rendre la conf surchargeable au moyen de variables d’environnement, ou par des options en ligne de commande, etc.).
  • Pour faciliter l’écriture des tests auto (avec une interface un peu plus sympa que juste les modules standards de Go), j’utilise testify, qui vient se greffer sur la toolchain classique (go test).
  • Tout ça est monitoré avec Prometheus, pour lequel il y a évidemment une bibliothèque en Go, et même, dans le cas de gRPC, un middleware qui prend et expose les mesures d’utilisation de base pour toi.

Pour le reste, ça dépend vraiment de ton infra. Vu que j’avais carte blanche dessus, dans mon cas tout est conteneurisé et tourne dans un cluster Kubernetes sur Google Cloud, ce qui me facilite beaucoup la tâche. Je vois que ton infra actuelle tourne sur du Azure : ils ont aussi une offre Kubernetes managée si jamais tu veux envisager ce genre de chose : quitte à être moderne… :D

En raison de ce choix, j’utilise zap pour mes logs, avec un petit adapteur pour que le format corresponde à celui de Stackdriver (la tech utilisé par Google Cloud), ce qui me permet d’avoir des logs structurés et bien formatés dans ma console Google Cloud, et évidemment, là aussi, un middleware grpc qui va logger les accès et les codes de retour.

Dans le cas où tu ne voudrais pas utiliser grpc, je pense que le framework HTTP le plus populaire à l’heure actuelle en Go est gin, que tu peux parfaitement utiliser avec les autres trucs cités ici (migrate, testify, zap, cobra, viper, gorm…).

+1 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte