Éliminer les temps d’arrêt par le biais des mises à jour de service avec version

Historiquement, les administrateurs devaient mettre un serveur hors ligne pour mettre à jour et améliorer les logiciels sur site. Cependant, les temps d’arrêt sont inacceptables pour les services internationaux opérant 24 heures sur 24, 7 jours sur 7. De nombreux services cloud modernes sont essentiels pour que les utilisateurs gèrent leurs activités. Il n’y a jamais de moment idéal pour mettre un système hors-ligne, alors comment une équipe peut-elle assurer un service continu tout en installant des mises à jour de sécurité et de fonctionnalités importantes ?

En utilisant des mises à jour par version, ces services critiques peuvent être transférés en toute transparence d'une version à l'autre pendant que les clients les utilisent activement. Les mises à jour ne sont pas toutes difficiles. Mettre à jour les mises en page ou les styles frontend est facile. Les modifications des fonctionnalités peuvent être délicates, mais il existe des pratiques bien connues pour atténuer les risques de migration. Cependant, les modifications qui émanent de la couche des données introduisent une nouvelle classe de complications qui nécessitent une attention particulière.

Mettez à jour les couches séparément

Avec un service en ligne distribué dans plusieurs centres de données et un stockage de données séparé, tout ne peut pas changer simultanément. Si le service typique est divisé en code d’application et bases de données, qui sont supposément versionnés indépendamment les uns des autres, l’une de ces parties doit absorber la complexité de la gestion des versions.

La gestion des versions est souvent plus simple à gérer dans le code de l’application. Les systèmes plus importants ont généralement beaucoup de code hérité, comme du SQL qui réside dans leurs bases de données. Plutôt que de compliquer davantage ce SQL, le code d’application devrait gérer la complexité. Plus précisément, vous pouvez créer un ensemble de classes de fabrique qui comprennent la gestion des versions SQL.

À chaque sprint, créez une nouvelle interface avec cette version pour qu’il y ait toujours un code correspondant à chaque version de la base de données. Vous pouvez facilement revenir en arrière sur n’importe quel code binaire lors du déploiement. Si quelque chose ne va pas après le déploiement des nouveaux codes binaires, revenez au code précédent. Si le déploiement des codes binaire réussit, démarrez la maintenance de la base de données.

Alors comment cela fonctionne-t-il réellement ? Par exemple, supposons que votre équipe déploie actuellement le Sprint 123. Les codes comprennent le schéma de base de données du Sprint 123 et le schéma du Sprint 122. Le modèle général consiste à travailler avec les versions/sprints N et N-1 du schéma SQL. Les codes binaires interrogent la base de données, déterminent la version du schéma à laquelle ils sont connectés, puis chargent la liaison appropriée. Ensuite, le code d’application gère le cas où le nouveau schéma de données n’est pas encore disponible. Une fois que la nouvelle version est disponible, le code d’application peut commencer à utiliser la nouvelle fonctionnalité activée par la dernière version de la base de données.

N’effectuez de restauration par progression que pour la couche de données

Une fois les bases de données mises à niveau, le service est dans une situation de restauration par progression en cas de problème. Les migrations de base de données en ligne sont complexes et souvent multi-étapes. La restauration par progression est donc généralement la meilleure façon de résoudre un problème. En d’autres termes, si la mise à niveau échoue, la restauration échouerait probablement aussi. Il y a peu d’intérêt à investir dans les efforts de création et de test de code de restauration que votre équipe ne pense probablement jamais utiliser

Séquence de déploiement

Considérez un scénario où vous devez ajouter un ensemble de colonnes à une base de données et transformer certaines données. Cette transition doit être invisible pour les utilisateurs, il s’agit donc autant que possible les verrous de table, puis de maintenir les verrous pendant la plus courte période possible afin qu’ils ne soient pas perceptibles.

La première chose à faire est de manipuler les données, éventuellement dans des tables parallèles à l’aide d’un déclencheur SQL pour maintenir la synchronisation des données. Les migrations et les transformations de données importantes doivent parfois se faire en plusieurs étapes sur plusieurs déploiements sur plusieurs sprints.

Une fois les données supplémentaires ou le nouveau schéma créé en parallèle, l’équipe passe en mode déploiement pour le code de l’application. En mode déploiement, lorsque le code effectue un appel à la base de données, il prend d’abord un verrou sur le schéma, puis le libère après l’exécution de la procédure stockée. La base de données ne peut pas changer entre le moment où l’appel à la base de données est émis et l’exécution de la procédure stockée.

Le code de mise à niveau agit comme un rédacteur de schéma et demande un verrou d’écriture sur le schéma. Le code d’application a la priorité pour prendre un verrou de lecteur, et le code de mise à niveau reste en arrière-plan en essayant d’acquérir le verrou d’écriture. Sous le verrou d’écriture, seules un petit nombre d’opérations très rapides sont autorisées sur les tables. Ensuite, le verrou est libéré et le code d’application enregistre la nouvelle version de la base de données en cours d’utilisation et utilise l’interface correspondant à la nouvelle version de la base de données.

Les mises à niveau de la base de données sont toutes effectuées selon un modèle de migration. Un ensemble de code et de scripts examine la version de la base de données, puis apporte des modifications progressives pour migrer le schéma de l’ancienne version à la nouvelle. Toutes les migrations sont automatisées et déployées via un service de gestion des versions.

L’interface utilisateur Web doit également être mise à jour sans perturber les utilisateurs. Lors de la mise à jour des fichiers JavaScript, des feuilles de style ou des images, évitez de mélanger d’anciennes et de nouvelles versions chargées par le client. Cela peut entraîner des erreurs qui pourraient entraîner la perte de travaux en cours, tels qu’un champ édité par un utilisateur. Par conséquent, vous devez versionner tous les fichiers JavaScript, CSS et images en plaçant tous les fichiers associés à un déploiement dans un dossier distinct et versionné. Lorsque l’interface utilisateur Web effectue des appels au niveau du serveur d’application, les ressources avec une version spécifiée sont chargées. La nouvelle interface utilisateur Web est seulement chargée dans le navigateur lorsque l’action de l’utilisateur entraîne un rafraîchissement complet de la page. L’expérience de l’utilisateur n’est pas perturbée par la mise à niveau.

Étapes suivantes

Microsoft est l’une des plus grandes entreprises de développement de logiciels au monde depuis des décennies. Découvrez comment Microsoft exploite des systèmes fiables avec DevOps.