Les systèmes de production ne peuvent pas s'arrêter. Qu'il s'agisse de la plateforme financière traitant des transactions à 2 heures du matin, du système de dossiers médicaux au service des cliniciens répartis sur plusieurs fuseaux horaires ou de l'application logistique assurant le suivi des expéditions à travers les continents, aucun de ces systèmes ne dispose d'une fenêtre de maintenance permettant une refonte complète. Pourtant, tous accumulent une dette technique, conservent des choix d'architecture antérieurs et nécessitent, à terme, une refonte structurelle pour rester maintenables, évolutifs et sécurisés. La refonte sans interruption de service est la méthode qui résout cette tension : faire évoluer un système en production sans interrompre le service qu'il fournit.
Moderniser sans aucun temps d'arrêt
Refactorisez vos applications en direct en production avec un contrôle et une précision de niveau entreprise
Voir Plus SMART TS XLLe défi n'est pas uniquement technique. Il est aussi organisationnel et architectural. La refonte d'un système qui ne peut être mis hors ligne exige une approche différente de celle de la refonte d'un système en développement : chaque modification doit être rétrocompatible jusqu'à ce qu'elle ne le soit plus, chaque transition structurelle doit être réversible et chaque validation doit être effectuée sur du trafic réel plutôt que sur des tests synthétiques. Les techniques qui rendent cela possible, telles que les déploiements bleu-vert, les bascules de fonctionnalités, le modèle de la figue étrangleuse, les migrations de bases de données par expansion-contraction et les architectures événementielles idempotentes, sont individuellement bien documentées. Ce qui est moins souvent abordé, c'est la manière dont elles interagissent pour former une stratégie cohérente permettant une évolution structurelle durable et sécurisée des systèmes qui doivent servir les utilisateurs tout au long du processus.
Architecture requise pour des modifications sans interruption de service
La question la plus fréquente que se posent les équipes qui s'engagent dans une refactorisation sans interruption de service est d'ordre architectural : que faut-il modifier dans la conception du système avant de pouvoir commencer la refactorisation ? La réponse ne réside pas dans un modèle unique, mais dans un ensemble de propriétés structurelles qu'un système doit respecter pour qu'une refactorisation en production soit possible en toute sécurité. La compréhension de ces propriétés est indispensable pour la suite de ce guide.
La première propriété est l'indépendance de déploiement. Chaque composant à refactoriser doit pouvoir être déployé sans nécessiter le déploiement simultané de ses dépendances. Si la modification du service A requiert la modification simultanée des services B et C pour éviter toute interruption de service, un déploiement de A sans interruption de service est structurellement impossible : les trois services forment de fait une seule unité de déploiement, quel que soit le nombre de dépôts où ils résident. L'indépendance de déploiement exige des interfaces rétrocompatibles, des contrats versionnés et l'élimination des exigences de déploiement coordonné entre les services.
La seconde propriété est la réversibilité. Tout déploiement modifiant le comportement en production doit être réversible en quelques minutes, et non en quelques heures. La réversibilité ne se limite pas à la simple conservation de l'ancien binaire. Elle exige que l'état de la base de données, l'état du cache, l'état de la session et tout état du système externe modifié par la nouvelle version soient compatibles avec l'ancienne version. Si une nouvelle version écrit des données dans un format illisible par l'ancienne version, le déploiement est par définition irréversible et une disponibilité continue est impossible, car toute restauration entraînera des erreurs.
La troisième propriété concerne les transitions d'état observables. Un effort de refactorisation qui déplace le comportement d'un chemin de code à un autre sans métriques observables sur les deux chemins est mené à l'aveugle. L'équipe ne peut pas savoir si la transition réussit ou échoue, ni détecter les régressions précocement, ni prendre de décisions basées sur les données quant au moment d'accélérer ou d'interrompre la migration. L'observabilité doit être instrumentée avant le début de la refactorisation, et non ajoutée après l'apparition d'un problème. Comme examiné dans le contexte de refactorisation progressive et dette techniqueLa visibilité structurelle du fonctionnement du code et de ses dépendances constitue le fondement de toute planification de changement qui ne peut se permettre d'échouer en production.
Déploiement bleu-vert : le modèle de référence
Le déploiement bleu-vert est le modèle de base pour les mises en production sans interruption de service. Deux environnements de production identiques existent : l’environnement bleu, qui gère le trafic en temps réel, et l’environnement vert, qui reçoit la nouvelle version. Cette dernière est déployée, testée et validée dans l’environnement vert, tandis que l’environnement bleu continue de servir les utilisateurs sans interruption. Une fois l’environnement vert validé, le trafic est basculé de manière atomique. La restauration s’effectue en sens inverse : le trafic est redirigé vers l’environnement bleu, qui reste disponible en permanence.
Le modèle semble simple. Sa difficulté réside dans la couche base de données. Lorsque les deux environnements doivent lire et écrire dans la même base de données, le schéma de cette dernière doit être compatible avec les deux versions simultanément. Une migration qui supprime une colonne, renomme un champ ou modifie un type de données perturbe l'ancien environnement dès son exécution. C'est pourquoi le déploiement bleu-vert est indissociable du modèle de migration de schéma « expansion-contrat » décrit dans la section « Base de données » de ce guide.
Techniques de lancement progressif et de déploiement par étapes
Les déploiements progressifs (ou déploiements Canary) étendent le modèle bleu-vert en acheminant un pourcentage du trafic vers la nouvelle version plutôt que de basculer tout le trafic simultanément. Un déploiement Canary peut débuter avec 1 % des utilisateurs, observer les taux d'erreur, la latence et les indicateurs de performance pour ce groupe, puis augmenter progressivement ce pourcentage : 5 %, 20 %, 50 %, 100 %. À chaque étape, des contrôles automatisés vérifient que les indicateurs clés ne se sont pas dégradés en dessous des seuils définis. En cas de défaillance d'un contrôle, le déploiement est interrompu et le pourcentage de déploiement Canary est ramené à zéro.
Les techniques de déploiement progressif ajoutent une logique de ciblage à cette progression. Au lieu de se baser uniquement sur un pourcentage, le trafic peut être segmenté par groupe d'utilisateurs, région géographique, niveau d'abonnement ou caractéristiques de session. Cela permet de valider la nouvelle version auprès de la population d'utilisateurs qui la sollicite le plus avant sa migration complète. L'exigence principale est que l'infrastructure de routage, qu'il s'agisse d'un équilibreur de charge, d'une passerelle API ou d'un maillage de services, prenne en charge la granularité de ciblage requise par le déploiement.
Les indicateurs de performance qui régissent les tests de validation doivent être définis avant le déploiement. Le taux d'erreur, la latence à 99 secondes (p99), le temps de requête à la base de données et les indicateurs spécifiques à l'activité, tels que le taux de conversion ou le taux de réussite des paiements, constituent autant de critères de validation valides. Les seuils de validation doivent être calibrés par rapport à une valeur de référence mesurée sur la version existante sous une charge comparable, et non par rapport à des objectifs théoriques. Un déploiement qui réussit un test de validation à 2 % du trafic mais échoue à 20 % n'est pas validé : l'échantillon testé était trop petit pour être représentatif. Un déploiement progressif réussi nécessite une exposition au trafic suffisante à chaque étape pour permettre une comparaison statistiquement significative.
Interrupteurs à bascule et coupe-circuits
Les commutateurs de fonctionnalités découplent le déploiement de code de l'activation des comportements. Un chemin de code refactorisé est déployé à l'état inactif, contrôlé par un commutateur qui détermine quels utilisateurs ou requêtes exécutent la nouvelle logique. Ce commutateur peut être activé progressivement, ciblé sur des groupes spécifiques, ou désactivé instantanément sans redéploiement. Les commutateurs de fonctionnalités constituent ainsi le principal mécanisme de migration sans interruption de service de la logique métier, contrairement aux modifications d'infrastructure pour lesquelles les modèles bleu-vert ou canari sont plus appropriés.
Les interrupteurs d'arrêt d'urgence sont l'équivalent défensif des commutateurs de fonctionnalités : leur but n'est pas d'activer un nouveau comportement, mais de le désactiver instantanément en cas de dysfonctionnement. Un interrupteur d'arrêt d'urgence appliqué à un calcul de facturation remanié, à un nouveau flux d'authentification ou à une couche d'accès aux données de remplacement offre à un ingénieur d'astreinte une procédure de récupération simple, sans déploiement, restauration de base de données ni coordination inter-équipes. Cet interrupteur doit être configuré dans un système permettant son déclenchement via un appel API, une console de gestion des indicateurs de fonctionnalités ou une intégration d'alerte automatisée, afin que le délai de déclenchement soit de quelques secondes et non de plusieurs minutes.
La gestion des commutateurs est un enjeu opérationnel majeur. Les commutateurs non nettoyés s'accumulent dans le code, complexifiant la compréhension du flux de contrôle et créant des dépendances implicites entre leur état et celui des données. Chaque commutateur doit avoir un responsable identifié, une date d'expiration prévue et un ticket de nettoyage. La dette liée aux commutateurs est une dette technique aussi réelle que toute autre, et elle s'accroît plus rapidement car les commutateurs protègent généralement les parties du système les plus fréquemment modifiées.
Refonte de base de données sans interruption de service
Les modifications de base de données représentent la partie la plus complexe de la refactorisation sans interruption de service, car les bases de données sont à état, partagées et lentes à modifier à grande échelle. Une application peut être déployée et restaurée en quelques minutes. En revanche, une migration de base de données modifiant une table contenant des centaines de millions de lignes peut prendre des heures, est difficilement réversible une fois validée et bloque les lectures et les écritures pendant toute la durée de l'opération. Réussir la refactorisation d'une base de données exige une approche différente de celle utilisée pour la refactorisation du code applicatif, et la plupart des équipes s'en rendent compte dès leur première tentative de modification de schéma sur une table en production à fort trafic.
Le principe fondamental est que toute modification de la base de données doit être rétrocompatible avec la version précédente de l'application jusqu'à la suppression définitive de cette dernière. Cela paraît évident, mais a des implications moins évidentes. Renommer une colonne nécessite l'ajout du nouveau nom comme alias ou doublon avant de pouvoir supprimer l'ancien. Modifier le type d'une colonne requiert la création d'une colonne fantôme du nouveau type, renseignée en parallèle, avant la suppression de l'ancienne colonne. Supprimer une table implique de s'assurer qu'aucune version déployée de l'application n'y accède. Chacune de ces opérations est un processus en plusieurs étapes, réparti sur plusieurs déploiements, et non une simple migration ponctuelle. Comme évoqué plus largement… Refactorisation COBOL à travers des structures de données existantes, le défi de faire évoluer les structures de données partagées entre plusieurs programmes et systèmes sans transition coordonnée est l'une des difficultés majeures de la refactorisation à l'échelle de l'entreprise.
Le modèle d'expansion-contraction
Le modèle d'expansion-contrat formalise l'approche en plusieurs étapes des modifications de schéma. Lors de la phase d'expansion, de nouveaux éléments de schéma sont ajoutés progressivement : une nouvelle colonne, une nouvelle table et un nouvel index. L'application est mise à jour pour écrire dans les anciennes et les nouvelles structures, mais continue de lire les données de l'ancienne structure. Aucune donnée n'est perdue, aucune requête existante n'est affectée et l'ancienne version de l'application reste fonctionnelle car les anciens éléments de schéma sont toujours présents.
Lors de la phase de contraction, qui intervient dans un déploiement distinct après le déploiement et la validation complets de la nouvelle version, les anciens éléments de schéma sont supprimés. À ce stade, aucune version en cours d'exécution de l'application n'en dépend. La suppression est sécurisée car elle a été vérifiée par observation et non supposée par planification.
Le modèle d'expansion-contrat exige une rigueur dans l'ordre de déploiement. La migration de base de données ajoutant la nouvelle colonne doit être déployée avant la version de l'application qui y écrit. La migration supprimant l'ancienne colonne doit être déployée après la mise hors service de toutes les versions de l'application qui y accèdent. Ces contraintes d'ordre doivent être intégrées au pipeline de déploiement afin d'éviter tout déploiement hors séquence des migrations.
Outils pour refactoriser les pipelines de données existants sans réécrire le code
Les pipelines de données existants, notamment ceux basés sur des frameworks de traitement par lots, des outils ETL ou des systèmes de déplacement de données mainframe, présentent un défi particulier : ils transforment et déplacent les données en continu, ne peuvent être interrompus pendant une migration et sont souvent si mal documentés que leur fonctionnement exact reste méconnu jusqu’à ce qu’un incident survienne. La refonte de ces pipelines, sans réécriture complète, nécessite des outils capables d’observer leur fonctionnement actuel, de vérifier que la version refondue produit un résultat équivalent et de permettre une transition progressive.
La capture des données modifiées (CDC) est l'outil le plus largement applicable pour la refactorisation en direct des pipelines. La CDC enregistre chaque opération d'écriture sur une table source sous forme de flux d'événements, permettant ainsi d'alimenter simultanément l'ancien pipeline et un nouveau pipeline de remplacement à partir de la même source, sans modification. L'ancien pipeline continue de fonctionner, le nouveau est exécuté en parallèle sur le même flux d'événements, et les résultats sont comparés. Les divergences permettent d'identifier la logique de transformation qui n'a pas été correctement réimplémentée. Une fois la parité confirmée, l'ancien pipeline est mis hors service.
Les outils de migration de schémas, tels que Liquibase et Flyway, proposent des migrations versionnées et séquencées, applicables de manière incrémentale et annulables grâce à la méthode d'expansion des contrats. Ils assurent le suivi des migrations appliquées à chaque environnement et empêchent leur application dans le désordre. Pour les pipelines existants exécutés sur des systèmes mainframe ou des bases de données VSAM, la gestion équivalente s'effectue via Gestion de l'expansion JCL et des ensembles de données qui contrôle la manière dont les programmes accèdent aux données pendant la transition, garantissant ainsi que ni l'ancien ni le nouveau programme ne s'exécutent sur une structure de données incompatible.
Comment moderniser les bases de données existantes sans interruption de service
Le défi spécifique que représente la modernisation d'une base de données existante, qu'il s'agisse de passer d'un schéma DB2 mainframe à une base de données relationnelle dans un environnement hébergé dans le cloud, de migrer d'une structure VSAM basée sur des fichiers vers un schéma relationnel ou de consolider plusieurs bases de données existantes dans un nouveau magasin unifié, exige l'application séquentielle de toutes les techniques susmentionnées sur une période prolongée.
L'approche qui a fait ses preuves est la suivante : commencer par la parité en lecture, puis atteindre la parité en écriture, migrer les lectures, puis les écritures, et enfin mettre hors service l'ancien système de stockage. La parité en lecture signifie que le nouveau système contient toutes les données de l'ancien et peut répondre à toutes les requêtes de l'application. La parité en écriture signifie que chaque écriture effectuée par l'application dans l'ancien système est également appliquée au nouveau, soit par des écritures simultanées dans l'application, soit par la réplication CDC. Une fois les deux conditions de parité confirmées en production, les lectures peuvent être migrées vers le nouveau système (après validation des résultats), puis les écritures, et enfin l'ancien système peut être mis hors service.
À aucun moment de cette séquence, le service n'est interrompu. À chaque étape, l'état précédent peut être restauré en réaffectant les lectures ou les écritures à l'emplacement de stockage précédent. La durée de chaque étape est déterminée par le niveau de confiance issu de la validation, et non par une date fixe.
Outils pour refactoriser les systèmes existants sans réécrire le code
Réécrire un système existant de A à Z est presque toujours plus coûteux et risqué qu'une refonte progressive. Une réécriture complète exige de maintenir simultanément l'ancien système en production tout en développant un système de remplacement aux fonctionnalités comparables, de gérer l'écart de parité fonctionnelle entre les deux et d'effectuer une migration, c'est-à-dire un déploiement sans interruption de service d'un système totalement différent. La plupart des organisations qui entreprennent une réécriture complète découvrent, en cours de route, que l'ancien système contenait des comportements non documentés, non reproduits par le système de remplacement et dont les utilisateurs dépendent.
La refactorisation incrémentale, grâce à des outils adaptés, permet d'éviter cet écueil en rendant l'ancien système lisible avant toute modification. Le point de départ est l'analyse structurelle : comprendre le rôle de chaque composant du système existant, ses dépendances et ses propres dépendances. Cette analyse ne peut être réalisée par la simple lecture de la documentation (généralement absente ou imprécise pour les systèmes hérités) ni par l'analyse manuelle et à grande échelle du code. Elle requiert des outils automatisés capables d'analyser le code existant, de construire un graphe de dépendances et de rendre ce graphe interrogeable. Comme décrit dans le contexte de… défis liés à la gestion de l'intégration des systèmes existantsLa première étape de tout programme de refactorisation de systèmes existants consiste à établir une visibilité structurelle qui n'existe dans aucun artefact maintenu par l'homme.
Le motif du figuier étrangleur pour les monolithes
Le modèle de architecture en forme de figuier étrangleur est la stratégie dominante pour remplacer progressivement un monolithe sans réécriture complète ni basculement. Les nouvelles fonctionnalités sont développées sous forme de services indépendants, en parallèle du monolithe. Une couche de routage, généralement une passerelle API ou un proxy inverse, intercepte les requêtes entrantes et les achemine soit vers le monolithe, soit vers le nouveau service, selon des règles de routage. Le monolithe continue de traiter tout le trafic non encore migré. Le nouveau service, quant à lui, ne gère que le trafic qui lui est explicitement acheminé.
Au fil du temps, de nouvelles règles de routage sont ajoutées. De nouveaux chemins sont dirigés vers de nouveaux services. Le système monolithique traite une part de plus en plus réduite du trafic total. Finalement, il ne traite plus aucun trafic et peut être mis hors service. Aucun déploiement individuel durant ce processus n'est suffisamment important pour représenter un risque significatif. Chaque modification de règle de routage est testable et réversible individuellement. La figure de l'étrangleur n'est pas une technique de transformation rapide : c'est une technique de transformation sécurisée sur des semaines, des mois ou des années, selon la complexité du système concerné.
L'exigence critique pour la mise en œuvre du modèle de figure en étranglement est que la couche de routage soit découplée à la fois du monolithe et des nouveaux services. Une couche de routage intégrée au monolithe ne peut pas acheminer le trafic en dehors de celui-ci. Le proxy doit se situer en amont des deux, capable de diriger le trafic vers l'un ou l'autre en fonction d'une configuration modifiable sans impacter ni le monolithe ni le nouveau service.
Refonte des API existantes en services natifs du cloud sans interruption de service
La migration d'une API existante vers une API native du cloud est une application spécifique du modèle de la figue étrangleuse avec des contraintes supplémentaires : l'API existante peut avoir des consommateurs qui ne peuvent pas être mis à jour simultanément, le contrat de l'API doit être maintenu tout au long de la transition et l'API native du cloud peut avoir des caractéristiques de performance différentes qui affectent les consommateurs de manière inattendue.
L'approche standard consiste à déployer l'API native du cloud derrière le même contrat d'API que l'API existante, à acheminer un pourcentage du trafic vers cette nouvelle API via une méthode de déploiement progressif, à valider la parité des sorties pour ce pourcentage de trafic, puis à augmenter progressivement le pourcentage acheminé. Les utilisateurs n'ont rien à modifier pendant cette transition, car le contrat d'API est préservé. La couche de routage gère la transition de manière transparente.
La transition sans interruption de service des intégrations principales vers les API intermédiaires, qui apparaît comme une requête importante dans les données de la Search Console pour cet article, correspond précisément à ce scénario : le moment où la couche de routage est mise à jour pour diriger l'intégralité du trafic vers le nouveau système et où l'ancienne API est mise hors service. Cette transition ne doit jamais être un événement ponctuel. Elle doit constituer l'étape finale d'un déploiement progressif ayant déjà validé le nouveau système avec des taux de trafic de plus en plus élevés. Au moment de la transition finale, le nouveau système a déjà géré l'intégralité du volume de trafic ; la transition supprime simplement le chemin de secours devenu inutile.
Idempotence, nouvelles tentatives et basculement dans les systèmes remaniés
La refonte d'un système utilisant une architecture événementielle, des files d'attente de messages ou des appels de services distribués soulève des problèmes que les modèles axés uniquement sur le déploiement ne permettent pas de résoudre : que deviennent les opérations en cours lors du passage d'un service de l'ancienne à la nouvelle version ? Les événements publiés sous l'ancienne version peuvent parvenir à un gestionnaire exécutant la nouvelle version. Les requêtes initiées auprès de l'ancienne API peuvent parvenir à un gestionnaire ayant déjà été remanié selon une nouvelle structure interne. Les transactions partiellement exécutées sous l'ancienne logique peuvent nécessiter d'être finalisées ou compensées sous la nouvelle logique.
La solution à tous ces problèmes réside dans l'idempotence : concevoir chaque opération de manière à ce qu'elle produise le même résultat, qu'elle soit exécutée une ou plusieurs fois. Un gestionnaire idempotent qui reçoit un événement dupliqué lors d'une transition de déploiement produit la même sortie qu'un gestionnaire qui reçoit l'événement une seule fois. Une opération d'écriture idempotente rejouée lors d'une restauration produit le même état de la base de données que l'écriture initiale. L'idempotence n'est pas seulement une préoccupation liée à la refactorisation : c'est une propriété générale des systèmes distribués résilients. Or, c'est lors des transitions de refactorisation que son absence engendre les défaillances les plus visibles.
Ajout de nouvelles tentatives et de basculement de fournisseur sans refonte majeure
L'une des questions les plus fréquentes dans les données de la Search Console pour cet article concerne l'ajout de fonctionnalités de nouvelle tentative et de basculement à une application existante, notamment une application Rails ou utilisant un framework similaire, sans nécessiter une refonte complète. La réponse est que ces fonctionnalités peuvent être intégrées de manière transversale au niveau de l'infrastructure, sans modifier les implémentations des services individuels.
Au niveau de l'infrastructure, un maillage de services comme Istio ou Linkerd peut être configuré pour relancer automatiquement les requêtes ayant échoué, jusqu'à un nombre de tentatives défini, avec un délai exponentiel et une gigue afin d'éviter les comportements de type « tonnerre ». Ceci ne nécessite aucune modification du code applicatif, car le comportement de relance est implémenté dans le proxy sidecar qui intercepte toutes les requêtes entrantes et sortantes. La bascule vers un fournisseur secondaire peut être implémentée de manière similaire : si le fournisseur principal renvoie un taux d'erreur supérieur à un seuil prédéfini, le maillage achemine les requêtes suivantes vers un fournisseur secondaire jusqu'à ce que le fournisseur principal soit rétabli.
Au niveau applicatif, lorsque les tentatives de nouvelle exécution au niveau de l'infrastructure sont insuffisantes car la logique de nouvelle exécution doit tenir compte de l'état métier, une bibliothèque de nouvelles exécutions légère ou une file d'attente de tâches peut être introduite à la frontière entre l'application et ses dépendances externes, sans restructurer l'application en interne. L'essentiel est d'isoler la logique de nouvelle exécution et de basculement à la frontière d'intégration plutôt que de la distribuer dans toute la couche métier. Cela rend le comportement de nouvelle exécution visible, testable et configurable sans toucher à la structure principale de l'application. Comme évoqué dans le contexte de… pratiques de refactoring agileL'introduction de modèles de fiabilité au niveau de l'infrastructure avant la refactorisation de la logique métier réduit la surface à valider après chaque modification.
Idempotence dans les architectures événementielles avec Redis Streams
Les architectures événementielles à faible latence utilisant Redis Streams ou des technologies similaires sont confrontées à un défi d'idempotence spécifique lors de la refactorisation : les groupes de consommateurs peuvent traiter les événements à des rythmes différents, le consommateur lisant les événements sous la nouvelle version peut avoir déjà traité des événements que l'ancienne version n'a pas traités, et les opérations de relecture ou de récupération peuvent livrer le même événement plusieurs fois à des gestionnaires qui n'ont pas été conçus pour gérer les doublons.
L'approche standard consiste à attribuer un identifiant unique à chaque événement lors de sa publication et à conserver ces identifiants dans un stockage persistant. Avant de traiter un événement, le gestionnaire vérifie si l'identifiant a déjà été utilisé. Si c'est le cas, l'événement est acquitté puis ignoré sans retraitement. Sinon, il est traité et son identifiant est enregistré. Cette logique de déduplication doit être atomique : si le gestionnaire traite l'événement mais échoue avant d'enregistrer son identifiant, l'événement sera retraité lors de la prochaine transmission. L'utilisation d'opérations atomiques Redis ou d'écritures transactionnelles pour enregistrer l'identifiant lors du traitement permet d'éviter cette situation de concurrence.
Lors d'une transition de refactorisation au cours de laquelle la logique du consommateur change, les identificateurs d'idempotence offrent un avantage supplémentaire : ils permettent de rejouer le flux d'événements par rapport à la nouvelle logique du consommateur et de comparer les sorties avec les sorties enregistrées de l'ancienne logique du consommateur, permettant ainsi des tests de comparaison sans exposer les utilisateurs à la nouvelle logique.
Automatisation du refactoring dans les pipelines CI/CD
La rigueur du remaniement sans interruption de service ne peut être maintenue par des processus manuels. Chaque déploiement dans un programme de remaniement sans interruption de service exige une série de validations : des vérifications préalables de la compatibilité de la nouvelle version avec l’état actuel de la base de données, des évaluations par test de charge (canary gate) à chaque augmentation du trafic, une comparaison automatisée des résultats entre les anciens et les nouveaux chemins d’exécution, et une vérification post-déploiement du maintien des indicateurs clés de performance. Effectuer ces étapes manuellement pour chaque modification n’est pas viable opérationnellement et introduit des erreurs humaines aux points les plus critiques du processus.
Un pipeline CI/CD pour la refactorisation sans interruption de service n'est pas un simple pipeline de construction et de déploiement. C'est un pipeline de validation : une séquence de contrôles automatisés qui doivent tous être validés avant qu'une modification ne passe à l'étape de déploiement suivante. Chaque contrôle correspond à un critère spécifique et mesurable. L'échec d'un contrôle interrompt le pipeline et déclenche une alerte. La validation de tous les contrôles permet de passer automatiquement à l'étape suivante. Comme décrit dans la discussion plus générale de Pratiques CI/CD pour les environnements mainframe et d'entrepriseL’exigence fondamentale est que le pipeline applique la même discipline de déploiement à chaque modification, quelle que soit son ampleur, et que cette application soit automatisée plutôt que dépendante de l’attention d’ingénieurs individuels.
Étapes du pipeline pour la refactorisation en direct
Les points de contrôle d'étape sont les étapes de validation qu'un déploiement doit franchir avant de passer à l'étape suivante. Pour un pipeline de refactorisation sans interruption de service, l'ensemble minimal de points de contrôle est le suivant.
Avant le déploiement : une vérification de compatibilité du schéma confirme que la migration de la base de données est rétrocompatible avec la version actuelle de l’application, des tests de contrat automatisés vérifient que les réponses de l’API de la nouvelle version sont compatibles avec le contrat de la version précédente, et une analyse statique des dépendances confirme qu’aucune dépendance introduite par la nouvelle version n’entrera en conflit avec une dépendance requise par l’environnement existant.
Après le déploiement en mode canary : comparaison du taux d’erreur entre le trafic canary et le trafic de référence, comparaison de la latence aux points p50, p95 et p99, comparaison des indicateurs métier pour tout indicateur affecté par le chemin de code modifié et une fenêtre d’observation minimale pendant laquelle le mode canary doit rester stable avant que le pourcentage de trafic ne soit augmenté.
Après le déploiement complet : suite de tests de régression sur les points de terminaison de production, vérifications de cohérence de la base de données confirmant que toute migration à double écriture ou à contrat étendu a maintenu la cohérence, et confirmation que l’artefact de déploiement précédent reste disponible pour la restauration.
Refonte et application axées sur la conformité
La refactorisation axée sur la conformité introduit une contrainte supplémentaire que les points de contrôle du pipeline doivent respecter : chaque modification doit être manifestement conforme aux exigences réglementaires ou aux politiques organisationnelles applicables. Dans les secteurs réglementés, cela signifie que le pipeline de déploiement doit générer une piste d'audit indiquant les modifications apportées, la date de déploiement, les validations effectuées et les personnes ayant approuvé la modification. Les points de contrôle automatisés du pipeline, qui enregistrent leur propre exécution (état des entrées, critères de validation et résultat : réussite/échec), fournissent cette piste d'audit sans intervention manuelle.
Les plateformes de refactoring intelligentes dotées de capacités d'application à l'échelle de l'équipe, qui apparaissent comme une requête dans les données de la Search Console pour cet article, sont des outils qui intègrent la validation de la conformité au flux de travail de refactoring : elles garantissent l'application cohérente des modèles de refactoring entre les équipes, la non-réintroduction d'interfaces obsolètes et la conformité des modifications structurelles aux normes architecturales définies au niveau de l'organisation. Ces fonctionnalités vont au-delà de ce qu'offre un pipeline CI/CD classique, car elles nécessitent une compréhension de la sémantique du code modifié, et pas seulement sa compilation et la réussite des tests.
Refonte des systèmes mainframe et CICS sans interruption de service
Les environnements mainframe représentent le cas le plus exigeant de refactorisation sans interruption de service, car les contraintes sont structurelles et non configurables. Un programme transactionnel CICS ne peut être remplacé par le simple déploiement d'une nouvelle image conteneur et le changement d'équilibreur de charge. Le remplacement d'un programme CICS nécessite une commande NEWCOPY ou PHASEIN, qui charge une nouvelle version du programme en mémoire. NEWCOPY remplace immédiatement l'ancienne version, affectant toutes les transactions qui démarrent après son exécution. PHASEIN attend la fin de toutes les transactions actives utilisant l'ancienne version avant de la remplacer, assurant ainsi une transition plus fluide pour les transactions de longue durée.
Aucun de ces mécanismes ne permet une restauration instantanée. Si la nouvelle version du programme présente un défaut, le retour à l'ancienne version nécessite la réémission de NEWCOPY ou PHASEIN avec le module de chargement précédent. Cela implique que ce module soit conservé dans la bibliothèque de chargement et que la procédure de restauration soit documentée, répétée et exécutable par l'équipe d'astreinte sans intervention du développeur initial.
Les fichiers VSAM partagés ajoutent une contrainte supplémentaire. Plusieurs transactions CICS et programmes par lots peuvent accéder simultanément au même fichier VSAM. Toute modification structurelle de la mise en page du fichier, comme l'ajout ou l'extension d'un segment d'enregistrement, exige que tous les programmes y accédant soient mis à jour avant ou en même temps que cette modification, ou que le fichier prenne en charge plusieurs formats d'enregistrement pendant la période de transition. Il s'agit de l'équivalent, pour les systèmes mainframe, du modèle « extension-contrat » : la nouvelle mise en page doit être compatible avec les anciens programmes pendant la transition, et ces derniers doivent être mis à jour avant la mise hors service de l'ancienne mise en page. L'extension contrôlée des mises en page des ensembles de données et des paramètres d'accès des programmes est le mécanisme qui permet cette coexistence compatible sans remplacement de fichier.
Stratégies d'élimination des fenêtres de traitement par lots
Le traitement par lots traditionnel sur mainframe repose sur l'existence d'une fenêtre de traitement par lots : une période durant laquelle le traitement transactionnel en ligne est suspendu, les tâches par lots s'exécutent sans conflit et les données résultantes sont prêtes pour la prochaine période de traitement en ligne. Supprimer cette fenêtre de traitement par lots, indispensable à un fonctionnement véritablement sans interruption de service, implique de repenser le modèle de traitement par lots afin que les tâches puissent s'exécuter simultanément aux transactions en ligne sans corrompre les données partagées.
Les approches classiques consistent à verrouiller les ressources au niveau de l'enregistrement plutôt qu'au niveau du fichier, à utiliser le traitement par mini-lots événementiel qui traite les petites charges de travail en continu plutôt que les grosses de manière périodique, et à utiliser des bases de données à répliques de lecture qui prennent en charge les charges de travail de reporting par lots sans entrer en concurrence avec le traitement transactionnel en ligne pour l'accès en écriture. Chacune de ces approches nécessite des modifications des programmes et des modèles d'accès aux données, mais aucune n'exige le maintien de la fenêtre de traitement par lots pendant la transition : cette dernière peut être effectuée par étapes en utilisant la même approche de validation en deux phases que pour toute autre refonte de système en production.
Refactorisation de programmes COBOL par analyse d'impact
Pour refactoriser un programme COBOL en toute sécurité, il est indispensable de connaître, avant toute modification, les programmes qui l'appellent, les copybooks qu'il partage, les jeux de données qu'il lit et écrit, et les systèmes en aval qui dépendent des données qu'il produit. Sans cette connaissance structurelle, toute modification du programme comporte des risques inconnus : le programme refactorisé peut perturber un appelant non identifié, produire une sortie dans un format illisible par un système en aval, ou modifier une structure de données partagée d'une manière qui affecte d'autres programmes utilisant le même copybook.
L'analyse d'impact automatisée résout ce problème en construisant un graphe de dépendances complet du programme COBOL avant le début de la refactorisation. Ce graphe présente chaque appelant, chaque copybook partagé, chaque accès à un jeu de données et chaque consommateur en aval, organisés par type de relation et emplacement de référence spécifique. Le plan de refactorisation est ensuite dérivé de ce graphe d'impact : les programmes appelant le programme modifié doivent être testés par rapport à la nouvelle version, les copybooks modifiés doivent être validés par rapport à tous les programmes qui les incluent, et les structures de jeux de données modifiées doivent être validées par rapport à tous les programmes accédant aux mêmes jeux de données. Comme décrit dans le solutions d'analyse d'impact Grâce à la capacité offerte par IN-COM, il existe une différence entre un programme de refactorisation qui découvre ses conséquences après le déploiement et un autre qui les quantifie avant.
Vérification, restauration et observabilité
La refonte sans interruption de service génère un flux de production continu qui doit être surveillé en permanence. Cette surveillance ne se limite pas à une simple vérification a posteriori du bon fonctionnement du système : elle constitue un contrôle actif à chaque étape du déploiement et représente le principal mécanisme de détection précoce des problèmes, permettant ainsi de prévenir tout impact sur l’utilisateur.
Le modèle de vérification pour la refactorisation sans interruption de service comporte trois niveaux. Le premier est la surveillance synthétique : des transactions scriptées simulent le comportement des utilisateurs et s’exécutent en continu en production, validant ainsi le bon déroulement des flux clés. Les moniteurs synthétiques détectent les défaillances survenant dans des portions de code spécifiques que les utilisateurs réels n’empruntent généralement pas en période de faible trafic, et ils fournissent un comportement de référence permettant de comparer les résultats des tests de validation.
La deuxième couche est la surveillance différentielle : comparaison en temps réel des indicateurs entre le déploiement progressif et le déploiement de référence, notamment les taux d’erreur, les distributions de latence, les indicateurs métier et la consommation de ressources. La surveillance différentielle ne requiert pas de seuils absolus ; elle repose sur une comparaison relative. Un déploiement progressif présentant un taux d’erreur supérieur de 2 % à celui de référence constitue un problème, que le taux d’erreur absolu dépasse ou non un seuil défini individuellement.
La troisième couche concerne la vérification de la cohérence des données. Lors de toute refactorisation impliquant des écritures simultanées, des migrations de schéma ou des exécutions système en parallèle, la cohérence des données entre les anciennes et les nouvelles représentations doit être validée en continu. Les comparaisons de sommes de contrôle, les comparaisons du nombre d'enregistrements et les requêtes de vérification ponctuelles qui contrôlent les valeurs de champs spécifiques par rapport aux transformations attendues contribuent toutes à garantir le bon fonctionnement de la couche de données pendant la transition. Comme examiné dans le contexte de Qu’est-ce que l’analyse d’impact et pourquoi est-elle importante ?La capacité à vérifier les conséquences d'une modification par rapport à un ensemble défini d'attentes est ce qui distingue la refactorisation structurée du changement spéculatif.
Mécanismes de restauration instantanée
Un plan de restauration qui prend trente minutes à exécuter n'est pas adapté à un système à disponibilité continue. Pendant ce temps, les utilisateurs subissent déjà trente minutes de service dégradé. Une restauration instantanée exige que chaque déploiement soit conçu pour être réversible dès le départ, et non ajouté a posteriori lorsqu'un problème survient.
Pour les déploiements d'applications, la restauration instantanée implique de conserver l'artefact de déploiement précédent disponible, pré-initialisé et pointant vers le même état de la base de données. Un changement de trafic via un équilibreur de charge ou une modification des règles de la passerelle API devrait suffire pour revenir à la version précédente. Ceci est possible lorsque l'état de la base de données est rétrocompatible avec la version précédente, ce qui est garanti par la discipline « expand-contract » dans la couche de migration de la base de données.
Pour les migrations de bases de données, la restauration instantanée exige que chaque migration appliquée lors de la phase d'extension soit réversible sans perte de données. Une colonne ajoutée lors de cette phase peut être supprimée lors d'une restauration. En revanche, une colonne modifiée de manière destructive ne peut être restaurée sans sauvegarde. C'est pourquoi les modifications de schéma destructives, telles que la suppression de colonnes, la modification de types incompatibles ou la réduction de la précision, ne doivent jamais être appliquées tant que la nouvelle version n'est pas entièrement déployée et validée et que l'ancienne n'est pas définitivement mise hors service.
Comment SMART TS XL Prend en charge les programmes de refactorisation sans interruption de service
SMART TS XL Cette solution résout le problème de visibilité structurelle à l'origine de tous les échecs de refactorisation sans interruption de service : les équipes qui tentent de refactoriser des systèmes en production sans avoir une vision complète de leur contenu, des interdépendances entre eux et des conséquences de chaque modification prévue. La plateforme ingère le code source de tous les langages et plateformes de l'environnement, notamment COBOL, JCL, Java, .NET, Python, JavaScript et SQL, et construit un modèle de référence croisée unifié qui représente les relations structurelles de l'ensemble du système.
Avant qu'une modification de refactorisation ne soit effectuée, SMART TS XLLa fonctionnalité d'analyse d'impact de [Nom de l'outil] retrace le graphe de dépendances depuis le composant modifié jusqu'à chaque appelant, chaque structure de données partagée, chaque consommateur en aval et chaque programme affecté par la modification. Il en résulte une liste précise et détaillée des conséquences, classées par gravité et par composant, et non une évaluation générale des risques. Cette liste permet de planifier correctement une séquence de refactorisation sans interruption de service : elle indique quels consommateurs doivent être mis à jour avant le déploiement du composant modifié, quelles migrations de bases de données doivent être effectuées avant quels déploiements d'applications et quels systèmes en aval doivent être validés avant la mise hors service de l'ancienne version.
SMART TS XLLa fonctionnalité de visualisation du code de [nom de l'outil] permet aux équipes qui ne maîtrisent pas parfaitement chaque couche du système en cours de refactorisation de naviguer dans le graphe des dépendances. Les architectes peuvent ainsi visualiser les connexions entre les composants avant de repenser leur structure. Les développeurs peuvent identifier les appels à une fonction avant d'en modifier la signature. Les équipes d'exploitation peuvent voir comment un jeu de données est utilisé avant d'en modifier la disposition. Cette visibilité est indispensable à la mise en œuvre d'un programme de refactorisation structuré, réversible et par étapes, garantissant une disponibilité continue.
La refactorisation sans interruption de service comme pratique continue
Les techniques présentées dans ce guide ne sont pas des interventions ponctuelles. Elles constituent le vocabulaire opérationnel d'une organisation de développement qui a choisi de considérer les systèmes de production comme évolutifs en continu plutôt que comme des systèmes périodiquement remplacés. Les déploiements bleu-vert, les déploiements progressifs, l'activation/désactivation de fonctionnalités, les migrations par extension de contrat, l'extraction de fichiers étrangleurs, le traitement idempotent des événements et les contrôles de déploiement par pipeline ne sont pas des procédures d'urgence : ce sont les procédures opérationnelles standard d'une équipe qui déploie des modifications structurelles en toute sécurité et à haute fréquence.
Pour atteindre cet objectif, il est nécessaire d'investir dans les outils, l'infrastructure et les pratiques organisationnelles, bien au-delà d'une simple initiative de refactorisation. Les outils doivent permettre un déploiement indépendant, des transitions d'état observables et une restauration instantanée. L'infrastructure doit prendre en charge la répartition du trafic, les environnements bleu-vert et la synchronisation des données basée sur le CDC. Les pratiques organisationnelles doivent inclure une analyse d'impact avant déploiement, une surveillance différentielle après déploiement et des exercices réguliers de restauration afin de confirmer le bon fonctionnement du processus de restauration dans des conditions réalistes.
Les organisations qui réalisent cet investissement constatent que le coût par modification diminue à mesure que la pratique se perfectionne : chaque refactorisation successive est moins risquée que la précédente car l’infrastructure de support est déjà en place, l’équipe a acquis le discernement nécessaire pour déterminer les seuils de validation appropriés à chaque modification, et les connaissances structurelles accumulées dans des outils comme SMART TS XL Chaque modification planifiée est ainsi circonscrite avec plus de précision que la précédente. L'objectif de la refactorisation sans interruption de service n'est pas d'effectuer une seule modification en toute sécurité, mais de réaliser chaque modification en toute sécurité, de manière continue, sans jamais demander aux utilisateurs d'accepter une fenêtre de maintenance.