Publié le 03/03/2023 par Nicolas Coulon
La migration d’un Backend devant gérer des millions d’utilisateurs
Présentation
Mon Identifiant SNCF (MID) est la brique d’authentification et gestion des comptes clients de la SNCF. L’application doit gérer chaque jour des millions d’utilisateurs, et ce, de façon stable et sécurisée.
Contexte
Afin de centraliser les données et comptes de sa clientèle les services de la SNCF utilisent MID comme service d’authentification. Toute opération sur cette dernière met en jeu de nombreux éléments :
- La récupération des informations du client dans un LDAP et dans le Référentiel Client Unique (RCU)
- La gestion du cycle de vie de ces informations (RGPD)
- Le traitement et envoi de courriel au client
- Les facteurs d’authentification sécurisés, les cookies et la modification des informations de connexion du client
Compte tenu de sa complexité, le projet est divisé en plusieurs modules qui doivent interagir entre eux de façon fluide. Chacun de ces modules est géré par différentes équipes allant du développement même jusqu’au support en passant par le déploiement. La mise à jour du module gérant l’API était donc un point essentiel où il était important de tenir compte des services utilisés. Cette migration était nécessaire pour assurer les futures mises à jour de sécurité. En effet, il est important de rester dans des versions qui ont un support à long terme (LTS) afin de ne pas être exposé aux menaces sans pouvoir corriger les failles.
Java 8 approchant de sa fin de vie, la tâche de migrer notre API vers Java 17 m’a donc été confiée.
Les étapes
Lorsque j’ai récupéré cette mission, notre API suivait un processus précis.
- Génération d’interface Java depuis des spécifications API RAML
Cette étape récupère un fichier RAML et des fichiers JSON pour générer des interfaces Java décrivant le comportement que l’implémentation devra avoir. En l’occurrence, notre API retournait soit directement des JSON selon l’appel effectué, soit un code HTTP. Pour finir, le résultat de cette étape est emballé en tant que librairie que l’on importera dans notre API.
- Implémentation de la logique
Dans un second module, on importe la dépendance précédemment générée et on implémente la logique selon les interfaces données. Dans ce module, nous importons de nombreuses dépendances afin de gérer les modèles des différents courriels, la sécurisation des appels aux services internes et les traitements entre l’Access Manager et les différents services.
Dans ce processus, la première étape utilisait une librairie interne à la SNCF qui n’était pas compatible avec la version de Java visée. Afin de se détacher de cette dépendance tout en minimisant les impacts, j’ai choisi l’utilisation d’outils Open Source qui avaient plus de chance de recevoir des mises à jour, il s’agissait de OpenAPI generator. Pour fonctionner, j’ai tout d’abord converti le schéma RAML en schéma OpenAPI Specifications (OAS). Cependant, pour que OpenAPI Generator produise les résultats attendus, j’ai également créé un modèle Mustache permettant un grand contrôle sur la façon dont les interfaces Java seraient générées.
J’ai profité de ce remaniement pour faire en sorte que l’API envoie toujours le même type de réponse et donc d’éviter le fait que certains appels renvoient un JSON spécifique et d’autres uniquement un code HTTP. Ce changement implique donc des modifications sur l’intégralité des implémentations existantes ainsi que de leurs tests unitaires.
Maintenant que l’API se génère correctement, j’ai pu me concentrer sur la correction des librairies. En raison de l’interdépendance de leur interaction, ces dernières sont plus difficiles à corriger et à mettre à jour. Parmi les problèmes notables que j’ai pu rencontrer il y a eu :
- Les changements de répertoire Maven
- Les noms complets de librairies qui changent
- La nécessité d’ajouter un “Type Casting” explicite sur des objets qui sont déjà explicitement décrits
Après avoir apporté ces modifications, il était nécessaire de mettre à jour Spring afin de garantir notre compatibilité avec ses versions à venir. J’ai donc changé les modèles de courriel que l’on utilisait ainsi que le moteur qui traitait ceux-ci. En effet, nous utilisions un moteur qui était déprécié et qui allait être supprimé intégralement dans les futures versions de Spring. J’ai ainsi créé des modèles de courriel FreeMarker et j’ai totalement réécrit le code gérant les informations à insérer dans les différents courriels.
Le projet pouvant désormais compiler correctement, il suffisait de s’assurer que l’exécution se passe sans problème. Pour ce faire, notre API utilise un serveur Tomcat sur lequel on déploie une Web Archive (WAR). Même si le projet compile, toutes les librairies n’ont pas été conçues pour fonctionner nativement sur Java 17.
Cette version apporte un nombre non négligeable de changements sur le fonctionnement de la JVM. Parmi ces changements, ceux qui ont été impactants pour le projet sont l’encapsulation forte des API internes rendues obligatoires et la dépréciation de la réflexion sur les modules externes. Ces deux problèmes sont directement liés au fait que certaines librairies ne sont pas natives à Java 17. J’ai donc ajouté des options de JVM “—add-opens” et “—add-exports” pour s’assurer qu’il n’y aurait pas de problèmes. Ces changements ont dû également être effectués sur nos environnements par l’équipe des OPS.
Acteurs
Dans le cadre du projet de migration de notre API Spring de Java 8 vers Java 17, plusieurs acteurs interviennent :
- Agathe D., en tant que Lead Tech, apporte son assistance sur Spring et valide les changements proposés.
- Thierry B., en tant qu’Architecte, valide également les changements pour garantir leur conformité aux standards et à l’architecture globale du système.
- Nicolas COULON, en tant que Développeur, je suis responsable de réaliser la migration en elle-même, ainsi que de documenter les étapes et de présenter le résultat à l’équipe.
- L’équipe d’OPS, joue également un rôle clé dans ce projet, en effectuant les modifications nécessaires sur nos environnements afin de garantir une mise en production réussie de la nouvelle version de l’API. Leur expertise est essentielle pour s’assurer que tout fonctionne correctement dans le nouvel environnement Java 17.
Résultats
Pour moi cette mission était très enrichissante et m’a permis d’apprendre à trouver un bon compromis entre supporter des anciens processus et utiliser les dernières technologies. Cela m’a également permis de travailler ma communication technique. En effet, afin de trouver la solution qui convient le mieux au projet, il a été important de synthétiser et présenter les informations à l’architecte du projet ainsi que son Tech Lead afin qu’ils valident les changements ou dans le cas contraire, qu’ils m’aident à trouver une meilleure solution. J’ai pu par ailleurs écrire une documentation complète et précise de ce que j’ai réalisé pour non seulement la présenter aux membres de l’équipe, mais aussi pour les futurs projets qui en auraient éventuellement besoin. C’est pareillement un énorme atout pour moi, car selon mon chef de projet “je dois être l’une des seules personnes ayant effectué une telle migration”.
Pour CapGemini, cette mission est un succès, car elle était nécessaire pour répondre au besoin du client. De plus, la connaissance accumulée servira pour d’autres projets devant réaliser de telles migrations.
Avenir
Aujourd’hui, nous savons qu’Oracle a étendu le support de Java 8. Cependant, cette migration nous permet de prendre de l’avance et d’utiliser des technologies plus efficaces. Nous sommes actuellement en train de travailler sur une optimisation technique du projet qui n’aurait pas été possible sans Java 17. Il y a de plus en plus d’utilisateurs qui se connectent à l’aide de MID chaque jour et il est de notre devoir de nous assurer qu’ils n’ont pas de problème. Il est évident que d’autres migrations ou refontes auront lieu dans le futur pour accommoder cette croissance.
Critique
Il y a eu un effet “sous-marin” lors de la réalisation de cette mission. En effet, jusqu’à peu avant la fin, je ne communiquais pas assez sur mon avancée. Il était donc difficile pour le chef de projet et mon équipe de savoir où j’en étais et quels étaient mes problèmes. De plus aucune étude n’a été menée auparavant ce qui a rajouté un facteur ” surprises inattendues” pour moi. Depuis j’ai compris l’importance de pouvoir communiquer avec son équipe et de rapidement remonter les problèmes. Nous avons également pris l’initiative de toujours réaliser une étude avant toute tâche aussi importante ; ces études sont toujours scrupuleusement revues puis présentées à l’équipe et au client afin de ne plus avoir de “surprises inattendues”. Grâce à cela, j’ai de plus une forte connaissance du fonctionnement de notre API et de Java en général.
Encore à ce jour, je m’efforce de travailler ma communication qui reste ma plus grande faiblesse. Je prends également part à des sujets pouvant me forcer à communiquer tels que des études techniques, des revues de code ou d’études et des ” Workshops” pour parler ou présenter un sujet spécifique à l’équipe.
Compétences
Écrit par Nicolas Coulon
← Retour à l'accueil