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é.
Contexte
Afin de centraliser les données et comptes de sa clientèle les services de la SNCF utilise MID comme service d’authentification. Toute opération sur cette dernière met en jeux 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 ses informations (RGPD)
- Le traitement et envoie de courriel au client
- Les facteurs d’authentification sécurisés, les cookies et la modification de ses informations de connexion
Compte tenu de sa complexité, le projet est divisé en plusieurs modules qui doivent interagir en eux de façon fluide. Chacun de ses 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 mise à 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 menace 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é.
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 libraire 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 interne 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é. 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’autre 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. Ces dernières sont plus complexe à corriger et mettre à jour à cause de la multitude devant interagir entre elles. 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
Une fois ces changements effectués, il restait Spring à mettre à jour pour s’assurer de notre compatibilité avec ses futures versions. J’ai donc changé les modèles de courriel que l’on utilisait ainsi que le moteur qui traité 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 information à 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 changement sur le fonctionnement de la JVM. Parmi ces changements, ceux qui ont été impactant pour le projet sont l’encapsulation forte des API interne rendu obligatoire 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 native à 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 aurait en aurait é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’autre projet devant réaliser de telle migration.
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 lieux 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’à un 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é 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 remonté 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 à travailler ma communication qui reste ma plus grande faiblesse. Je prends également part à des sujets pouvant me forcer à communiquer tel que des études technique, des revue 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