web-dev-qa-db-fra.com

Comment déployer une application ASP.NET avec aucun temps d'arrêt

Pour déployer une nouvelle version de notre site Web, nous procédons comme suit:

  1. Compressez le nouveau code et téléchargez-le sur le serveur.
  2. Sur le serveur en direct, supprimez tout le code en direct du répertoire du site Web IIS.
  3. Extrayez le nouveau fichier zip de code dans le répertoire IIS

Ce processus est entièrement scripté et se produit assez rapidement, mais il peut toujours y avoir un temps d'arrêt de 10 à 20 secondes lorsque les anciens fichiers sont supprimés et les nouveaux fichiers déployés.

Des suggestions sur une méthode d'arrêt de 0 seconde?

126
Karl Glennon

Vous avez besoin de 2 serveurs et d'un équilibreur de charge. Voici les étapes:

  1. Transformez tout le trafic sur le serveur 2
  2. Déployer sur le serveur 1
  3. Serveur de test 1
  4. Transformez tout le trafic sur le serveur 1
  5. Déployer sur le serveur 2
  6. Serveur de test 2
  7. Transformez le trafic sur les deux serveurs

Le fait est que, même dans ce cas, vous aurez toujours des redémarrages d'application et une perte de sessions si vous utilisez des "sessions persistantes". Si vous avez des sessions de base de données ou un serveur d'état, alors tout devrait bien se passer.

79
Sklivvz

Microsoft Web Deployment Tool prend cela en charge dans une certaine mesure:

Active la prise en charge du système de fichiers transactionnels Windows (TxF). Lorsque la prise en charge TxF est activée, les opérations sur les fichiers sont atomiques; c'est-à-dire qu'ils réussissent ou échouent complètement. Cela garantit l'intégrité des données et empêche les données ou les fichiers d'exister dans un état "à mi-chemin" ou corrompu. Dans MS Deploy, TxF est désactivé par défaut.

Il semble que la transaction concerne l'intégralité de la synchronisation. En outre, TxF est une fonctionnalité de Windows Server 2008, donc cette fonctionnalité de transaction ne fonctionnera pas avec les versions antérieures.

Je pense qu'il est possible de modifier votre script pour 0-downtime en utilisant des dossiers comme versions et la métabase IIS:

  • pour un chemin d'accès/URL existant:
  • Copiez le site Web nouveau (ou modifié) sur le serveur sous
    • \ web\app\v2.1 \
  • Modifier IIS métabase pour changer le chemin du site Web
    • à partir de \web\app\2.0 \
    • à \web\app\v2.1 \

Cette méthode offre les avantages suivants:

  • En cas de problème avec la nouvelle version, vous pouvez facilement revenir à la version 2.0
  • Pour déployer sur plusieurs serveurs physiques ou virtuels, vous pouvez utiliser votre script pour le déploiement de fichiers. Une fois que tous les serveurs disposent de la nouvelle version, vous pouvez simultanément modifier les bases de données de tous les serveurs à l'aide de l'outil de déploiement Web Microsoft.
60
George Tsiokos

Vous pouvez obtenir un déploiement sans interruption de service sur un seul serveur en utilisant le routage des demandes d'application dans IIS comme équilibreur de charge logicielle entre deux sites locaux IIS sur différents ports. est connue sous le nom de stratégie de déploiement bleu vert où un seul des deux sites est disponible dans l'équilibreur de charge à un moment donné. Déployez sur le site qui est "down", réchauffez-le et placez-le dans l'équilibreur de charge (généralement en passant un contrôle de santé de routage de demande d'application), puis retirez le site d'origine qui était en haut, du "pool" (encore une fois en faisant échouer son contrôle de santé ).

n tutoriel complet peut être trouvé ici.

10
kavun

J'ai récemment vécu cela et la solution que j'ai trouvée était d'avoir deux sites configurés en IIS et de basculer entre eux.

Pour ma configuration, j'avais un répertoire Web pour chaque site A et B comme ceci: c:\Intranet\Live A\Interface c:\Intranet\Live B\Interface

Dans IIS, j'ai deux sites identiques (mêmes ports, authentification, etc.) chacun avec leur propre pool d'applications. L'un des sites fonctionne (A) et l'autre est arrêté (B). celui en direct a également l'en-tête de l'hôte en direct.

Quand il s'agit de déployer pour vivre, je publie simplement à l'emplacement du site ARRÊTÉ. Parce que je peux accéder au site B en utilisant son port, je peux préchauffer le site afin que le premier utilisateur ne provoque pas le démarrage d'une application. Puis en utilisant un fichier batch, je copie l'en-tête de l'hôte en direct vers B, arrête A et démarre B.

7
Rob King

À l'aide de la classe ServerManager de Microsoft.Web.Administration, vous pouvez développer votre propre agent de déploiement.

L'astuce consiste à modifier le PhysicalPath de VirtualDirectory, ce qui entraîne un basculement atomique en ligne entre les anciennes et les nouvelles applications Web.

Sachez que cela peut entraîner l'exécution simultanée d'anciens et de nouveaux AppDomains!

Le problème est de savoir comment synchroniser les modifications apportées aux bases de données, etc.

En recherchant l'existence d'AppDomains avec d'anciens ou de nouveaux PhysicalPaths, il est possible de détecter quand les anciens AppDomain se sont terminés et si les nouveaux AppDomain ont démarré.

Pour forcer un AppDomain à démarrer, vous devez effectuer une demande HTTP (IIS 7.5 prend en charge la fonction de démarrage automatique)

Vous avez maintenant besoin d'un moyen de bloquer les demandes pour le nouveau AppDomain. J'utilise un mutex nommé - qui est créé et détenu par l'agent de déploiement, attendu par Application_Start de la nouvelle application Web, puis publié par l'agent de déploiement une fois les mises à jour de la base de données effectuées.

(J'utilise un fichier marqueur dans l'application Web pour activer le comportement d'attente mutex) Une fois la nouvelle application Web en cours d'exécution, je supprime le fichier marqueur.

7
Jack

D'accord, puisque tout le monde vote contre la réponse que j'ai écrite en 2008 * ...

Je vais vous dire comment nous le faisons maintenant en 2014. Nous n'utilisons plus de sites Web parce que nous utilisons maintenant ASP.NET MVC.

Nous n'avons certainement pas besoin d'un équilibreur de charge et de deux serveurs pour le faire, c'est bien si vous avez 3 serveurs pour chaque site Web que vous gérez, mais c'est une surpuissance totale pour la plupart des sites Web.

De plus, nous ne comptons pas sur le dernier assistant de Microsoft - trop lent, et trop magique caché, et trop enclin à changer de nom.

Voici comment nous procédons:

  1. Nous avons une étape de post-construction qui copie les DLL générées dans un dossier "bin-pub".

  2. Nous utilisons Beyond Compare (qui est excellent **) pour vérifier et synchroniser les fichiers modifiés (via FTP car cela est largement pris en charge) jusqu'au serveur de production

  3. Nous avons une URL sécurisée sur le site Web contenant un bouton qui copie tout dans "bin-pub" vers "bin" (en prenant d'abord une sauvegarde pour permettre une restauration rapide). À ce stade, l'application redémarre d'elle-même. Ensuite, notre ORM vérifie s'il y a des tables ou des colonnes qui doivent être ajoutées et les crée.

Ce n'est qu'un temps d'arrêt de quelques millisecondes. Le redémarrage de l'application peut prendre une seconde ou deux, mais pendant le redémarrage, les demandes sont mises en mémoire tampon, il n'y a donc aucun temps d'arrêt.

L'ensemble du processus de déploiement prend de 5 secondes à 30 minutes, selon le nombre de fichiers modifiés et le nombre de modifications à examiner.

De cette façon, vous n'avez pas à copier un site Web entier dans un répertoire différent, mais uniquement le dossier bin. Vous avez également un contrôle total sur le processus et savez exactement ce qui change.

** Nous observons toujours rapidement les changements que nous déployons - comme une dernière vérification de dernière minute, nous savons donc quoi tester et si quelque chose se casse, nous sommes prêts. Nous utilisons Beyond Compare car il vous permet de différencier facilement des fichiers via FTP. Je ne ferais jamais ça sans BC, vous n'avez aucune idée de ce que vous écrasez.

* Faites défiler vers le bas pour le voir :( BTW, je ne recommanderais plus les sites Web car ils sont plus lents à créer et peuvent mal tomber avec des fichiers temporaires à moitié compilés. Nous les avons utilisés dans le passé car ils permettaient un fichier plus agile fichier par fichier Très rapide pour résoudre un problème mineur et vous pouvez voir exactement ce que vous déployez (si vous utilisez Beyond Compare bien sûr - sinon oubliez-le).

6
mike nelson

Les seules méthodes sans interruption de service auxquelles je peux penser consistent à héberger sur au moins 2 serveurs.

5
Sam Meldrum

Voici comment je le fais:

Configuration système minimale absolue:
1 serveur avec

  • 1 équilibreur de charge/proxy inverse (par exemple nginx) fonctionnant sur le port 80
  • 2 ASP.NET-Core/mono reverse-proxy/fastcgi chroot-jails ou docker-containers écoutant sur 2 ports différents TCP
    (ou même seulement deux applications de proxy inverse sur 2 ports différents TCP sans sandbox)

Flux de travail:

démarrer la transaction myupdate

try
    Web-Service: Tell all applications on all web-servers to go into primary read-only mode 
    Application switch to primary read-only mode, and responds 
    Web sockets begin notifying all clients 
    Wait for all applications to respond

    wait (custom short interval)

    Web-Service: Tell all applications on all web-servers to go into secondary read-only mode 
    Application switch to secondary read-only mode (data-entry Fuse)
    Updatedb - secondary read-only mode (switches database to read-only)

    Web-Service: Create backup of database 
    Web-Service: Restore backup to new database
    Web-Service: Update new database with new schema 

    Deploy new application to apt-repository 
    (for windows, you will have to write your own custom deployment web-service)
    ssh into every machine in array_of_new_webapps
    run apt-get update
    then either 
    apt-get dist-upgrade
    OR
    apt-get install <packagename>
    OR 
    apt-get install --only-upgrade <packagename>
    depending on what you need
    -- This deploys the new application to all new chroots (or servers/VMs)

    Test: Test new application under test.domain.xxx
    -- everything that fails should throw an exception here
    commit myupdate;

    Web-Service: Tell all applications to send web-socket request to reload the pages to all clients at time x (+/- random number)
    @client: notify of reload and that this causes loss of unsafed data, with option to abort 

    @ time x:  Switch load balancer from array_of_old_webapps to array_of_new_webapps 
    Decomission/Recycle array_of_old_webapps, etc.

catch
        rollback myupdate 
        switch to read-write mode
        Web-Service: Tell all applications to send web-socket request to unblock read-only mode
end try 
1
Stefan Steiger

Pour développer la réponse de sklivvz, qui reposait sur une sorte d'équilibreur de charge (ou simplement une copie de secours sur le même serveur)

  1. Diriger tout le trafic vers le site/serveur 2
  2. Attendez éventuellement un peu, pour vous assurer que le moins d'utilisateurs possible ont des flux de travail en attente sur la version déployée
  3. Déployez sur le site/serveur 1 et réchauffez-le autant que possible
  4. Exécuter des migrations de base de données de manière transactionnelle (s'efforcer de rendre cela possible)
  5. Dirigez immédiatement tout le trafic vers le site/serveur 1
  6. Déployer sur le site/serveur 2
  7. Trafic direct vers les deux sites/serveurs

Il est possible d'introduire un peu de test de fumée, en créant un instantané/copie de base de données, mais ce n'est pas toujours faisable.

Si possible et si nécessaire, utilisez des "différences de routage", telles que des URL de locataire différentes: (customerX.myapp.net) ou différents utilisateurs, pour déployer d'abord sur un groupe inconnu de cobayes. Si rien n'échoue, libérez tout le monde.

Étant donné que les migrations de base de données sont impliquées, revenir à une version précédente est souvent impossible.

Il existe des moyens de rendre les applications plus agréables dans ces scénarios, comme l'utilisation de files d'attente d'événements et de mécanismes de lecture, mais comme nous parlons de déployer des modifications sur quelque chose qui est en cours d'utilisation, il n'y a vraiment aucun moyen infaillible.

1
gliljas

Je raffinerais un peu la réponse de George, comme suit, pour un seul serveur:

  1. Utiliser un projet de déploiement Web pour précompiler le site dans une seule DLL
  2. Zip le nouveau site et téléchargez-le sur le serveur
  3. Décompressez-le dans un nouveau dossier situé dans un dossier avec les bonnes autorisations pour le site, afin que les fichiers décompressés héritent correctement des autorisations (peut-être e:\web, avec les sous-dossiers v20090901, v20090916, etc.)
  4. Utilisez IIS Manager pour changer le nom du dossier contenant le site
  5. Gardez l'ancien dossier autour pendant un certain temps, afin de pouvoir y revenir en cas de problème

L'étape 4 entraîne le recyclage du processus de travail IIS IIS).

Ce n'est que zéro temps d'arrêt si vous n'utilisez pas de sessions InProc; utilisez plutôt le mode SQL si vous le pouvez (encore mieux, évitez complètement l'état de la session).

Bien sûr, c'est un peu plus impliqué lorsqu'il y a plusieurs serveurs et/ou des changements de base de données ....

1
RickNZ