web-dev-qa-db-fra.com

Mettre à jour le site Web .NET sans recharger

J'avais l'habitude de développer des sites Web dans PHPet ASP classic et si quelque chose devait être changé. Vous pouvez simplement modifier un/plusieurs fichiers et personne ne le remarquera vraiment. Peut-être que quelqu'un demanderait le fichier modifié pendant le téléchargement, mais cela équivaut à une demi-seconde de marge. Ce n'est pas un problème pour la plupart des petits sites.

Mais les derniers sites ont été construits avec C#MVCet lorsque vous apportez des modifications au code, vous devez reconstruire votre site Web et télécharger les fichiers DLLmodifiés. Mais lorsque vous modifiez vos fichiers DLLname__, il redémarrera votre site Web et réinitialisera tous les actifs sessionsname__. Il faut également tout recharger et avec les grands sites, le chargement peut prendre quelques minutes. Tous ceux qui naviguaient sur le site le remarquaient et devaient se reconnecter.

Les mises à jour majeures de sites ne sont pas si courantes, donc ce n'est pas un problème. Mais nous avons régulièrement de "petites" mises à jour pour les promotions. Comme "Remplissez ce formulaire et obtenez trois mois d'abonnement gratuit" ou "Les 10 premiers à télécharger une image de ... recevront un prix". Je pense que vous aurez la dérive. Certaines promotions sont similaires et peuvent être gérées avec un module qui affiche les bonnes informations en fonction des paramètres, mais nécessite souvent un code personnalisé.

Je pensais à un système où chaque promotion est son propre fichier DLLbasé sur une interface, puis charge dynamiquement le DLLen utilisant Type.GetType, Activator.CreateInstance et InvokeMembername__. Bien que cela puisse fonctionner, je me demande si c'est la bonne façon de faire.

Donc, ma question est la suivante: comment mettre à jour un site .NET à la volée, sans recharger tout le site ni déposer de session (comme un pool d’applications recyclé).

13
Hugo Delsing

Rechercher dans "Initialisation de l'application" IIS 7.5, Windows 2008 R2 (plus difficile à installer) IIS 8, Windows 2012

L'initialisation de l'application permet à toute application (le pool d'applications et non au site) de redémarrer de se chevaucher et d'utiliser l'ancienne, tout en continuant d'exécuter l'application précédente lors du préchauffage du nouveau démarrage de l'application. Une fois que la nouvelle application est lancée (déterminée par les URL que vous pouvez définir), elle commence à utiliser la nouvelle application et ferme la précédente. L'utilisation de l'initialisation d'application en conjonction avec des méthodes pour garantir le maintien de la session lors du redémarrage d'un pool d'applications peut permettre à votre site de redémarrer de manière transparente. (Zhaph a une bonne note à propos de la clé machine.)

En plus des liens ci-dessus pour la configuration de l'initialisation de l'application, vous allez regarder ce qui déclenche le redémarrage du site - car le redémarrage du site n'utilise pas l'application Initiliazation le redémarrage du site ne sera pas transparent.

Vous pouvez configurer IIS de sorte qu'une mise à jour DLL ne déclenche pas immédiatement un redémarrage du site, pas plus que des modifications apportées à web.config (valeurs ChangeNotification élevées dans les fichiers httpRuntime et externes, le cas échéant). sur votre site).

Le résultat final est que vous pouvez mettre à jour les DLL/code sans redémarrer le site, puis forcer un redémarrage de l'application qui utilisera le préchauffage de l'arrière-plan AppInitialization pour la changement transparent du code.

Faire ces choses en concert fonctionne assez bien pour des redémarrages sans faille.

11
jeffreypriebe

Il y a plusieurs façons de gérer ce que vous demandez et quelques aspects différents de votre question:

Gérer de petites mises à jour pour les promotions

Ce que vous recherchez vraiment, c’est un système de gestion de contenu ou similaire qui vous permet d’éditer le contenu à la volée (pensez à Wordpress/Drupal ou d’un point de vue .NET, N2 CMS, Umbraco, Orchard, etc.). Y a-t-il des choses que vous pourriez essayer si vous ne vous êtes pas engagé dans cette voie?.

Comme ASP.NET ne recharge réellement que si vous touchez certains types de fichiers (web.config (s), le contenu des dossiers /bin/ et /app_code/ principalement) - et a une limite configurable pour "autre fichier changes "(en gros, une fois que vous aurez modifié autant de fichiers de votre site, le pool d’applications va redémarrer - NumRecompilesBeforeAppRestart ), vous pouvez essayer de faire quelque chose pour vérifier si un dossier différent contient des fichiers statiques (par exemple, .html) fichiers que vous extrayez et affichez selon vos besoins, ou utilisez la méthode LoadControl qui prend un chemin de chaîne vers un contrôle utilisateur .ascx et le charge dynamiquement - la façon de déterminer laquelle afficher est une question différente qui convient mieux StackOverflow - cependant, je recommanderais une solution basée sur la convention de nommage.

Vous pouvez également envisager d'utiliser quelque chose comme Managed Extensibility Framework (MEF - qui fait partie intégrante du framework .NET depuis la version 4), qui vous permet d'écrire une architecture basée sur un plugin et de spécifier un dossier. en dehors de votre répertoire /bin/ pour surveiller les nouveaux fichiers .DLL - bien que je n’aie pas essayé de voir si cela éviterait le problème de redémarrage de l’application, j’en ai fait bon usage dans un environnement Web pour ajouter des fonctionnalités communes à un site.

Si cela ne fait pas appel, la seule autre option à laquelle je puisse penser serait d’ajouter les contrôles comme "code-in-front" comme nous l’avions fait dans ASP classique - c’est-à-dire avec un bloc <script runat="server"> à la place. d'une classe "code-behind" compilée qui contient la logique pour exécuter le contrôle - cela supprime la nécessité d'une modification de DLL, au détriment d'une première perte de performances car le contrôle est compilé à la volée - Encore une fois, vous devrez équilibrer cela avec NumRecompilesBeforeAppRestart si vous faites beaucoup de petits changements.

Comment puis-je conserver des sessions lors du redémarrage d'une application?

C’est peut-être un problème plus facile à résoudre et comporte trois étapes clés:

  1. Configurez la MachineKey (IIS7, mais cela reste valable pour 8) est une valeur constante plutôt que AutoGenerate - cela signifie que lorsque l'AppPool recycle, il utilisera la même clé et pourra ainsi déchiffrer la session. cookies, viewstate, etc. d'avant le recyclage.
  2. Soit configurez un serveur d'état ou configurez une base de données pour conserver l'état de session .
  3. Passez de InProc à StateServer ou SQLServer dans l'élément SessionState de votre Web.config.

De cette façon, vous aurez des sessions persistantes qui survivent au redémarrage d'une application. Cependant, ils ne sont pas "gratuits" - tout ce que vous stockez dans une session doit maintenant être sérialisable et vous risquez une légère baisse de performances car chaque chargement de page nécessitera des déplacements supplémentaires sur le réseau pour pouvoir éventuellement libérer les données de la session.

Toutefois, si vous êtes dans une situation où il faut "plusieurs minutes" au redémarrage de l'application après un déploiement, vous pouvez envisager de passer à un environnement à charge équilibrée, ou au moins à une configuration Staging/Live échangeable à chaud. (tel que celui fourni par Azure/AWS/etc.) - de cette façon, vous pouvez mettre un serveur hors ligne pendant que vous le mettez à jour ou le préparer avec le nouveau code, puis l'échanger - à condition que vous ayez suivi les étapes pour régler l'adresse partagée. sessions (voir ci-dessus), cela fonctionnera sans effet pour vos utilisateurs.

5
Zhaph - Ben Duguid