Nouvelles Chroniques d'Amethyste

Penser au Sens, pas au Verbe

Relancer et initialiser automatiquement une application Web

Poster un commentaire

Il existe un certain nombre de circonstances dans lesquelles on a besoin de relancer automatiquement un site Web avant même qu’une requête client ne le fasse. Citons par exemple:

 

Ce problème est traditionnellement géré par un service et une tâche planifiée qui font le boulot, mais ce n’est pas toujours très pratique. Depuis ASP.NET 4.0 et IIS 7.5, on dispose de moyens standards pour relancer un site sans avoir à attendre l’arrivée d’une requête. Nous allons faire le point sur cette question dans cet article.

Note: IIS 7.5 ou 7.0? Je suis incertain faute d’être allé voir et à cause d’infos contradictoires glanées dans les forums. Disons que je suis certain que le support existe dans IIS 7.5, il faut juste brandir un peu de Web Platform Install.

Si le pool d’application recycle?

Important: La suite a été testée avec IIS 8.5 qui intègre un certain nombre de choses. Avec IIS 7 vous devrez éditer à la main le fichier:

 %windir%\System32\inetsrv\config\applicationHost.config

 

Vous trouverez les informations nécessaires ici:

http://www.iis.net/learn/get-started/whats-new-in-iis-8/iis-80-application-initialization#TOC301259898

Ou ici:

%windir%\system32\inetsrv\config\schema\IIS_schema.xml

 

La relation entre pool et worker process a été explorée ici:

https://amethyste16.wordpress.com/2014/08/13/worker-process-pool-dapplication/

 

Pour IIS 8 donc, ouvrir  les propriétés avancées du site dans IIS Manager:

2014-09-18_13-08-09

On place à true la propriété Préchargement Activé.

Cette option demande à IIS d’émettre une requête à blanc une fois que le pool de l’application à démarré. Encore faut t’il que le pool démarre, d’où le second paramétrage:

Dans les propriétés avancées du pool d’application qui héberge votre site:

2014-09-18_12-41-53

Fixez le mode de démarrage (StartMode) à AlwaysRunning. Si dans le même temps vous surveillez le gestionnaire de tâches de Windows, un processus w3wp démarre aussitôt:

 

2014-09-18_12-44-36

 

Vous devrez également installer le service d’initialisation de l’application:

2014-09-18_21-29-08

Pour les versions antérieures de IIS il faudra l’installer avec Web Platform Api.

 

Important: Sans ce service rien ne fonctionnera.

Justement faisons des tests. Commençons par une trace dans global_asax an ajoutant ceci dans Application_Start:

using (var flux = System.IO.File.CreateText(@"c:\temp\test.txt"))
{
   flux.WriteLine("hello");
}

 

On lance ensuite l’application dans IIS. Puis on recycle le pool d’application. Le fichier test.txt devrait apparaître.

Faites le même essai en relançant w3wp.exe, même résultat. L’explication se trouve ici:

https://amethyste16.wordpress.com/2014/08/13/worker-process-pool-dapplication/

 

Maintenant replacez préchargement activée (preloadEnabled) à false.

Cette fois le fichier ne réapparaît plus.

 

Amélioration facultative

Si l’initialisation est lente, il est peut être nécessaire d’afficher un message de maintenance pendant l’opération. Pour obtenir cet effet il faut se rendre dans le fichier de configuration du site.

<system.webServer>
    <applicationInitialization remapManagedRequestsTo="Maintenance.html" skipManagedModules="true">
        <add initializationPage="/" />
    </applicationInitialization>
</system.webServer>

Le fichier Maintenance.html est le fichier qui sera présenté à un utilisateur lorsque le serveur sera en train de s’initialiser. Les pages déclarées dans  initializationPage seront lancées par IIS pour initialiser l’application.

 

Et si c’est l’AppDomain qui redémarre?

Il existe différentes raisons qui peuvent conduire un AppDomain à redémarrer:

  •  Modification d’un fichier dans /bin
  • Lancer un Web deploy sur le site
  • Modifier web.config
  • L’application plante
  • Vous relancez le site

 

Vous constaterez facilement que dans ces situations, le mécanisme précédent ne se déclenche pas. C’est parce que le process w3wp.exe et donc le pool n’est pas recyclé.

Peut t’on alors faire quelque chose?

Une solution est de repinguer l’application dans l’événement Application_End afin de redémarrer le site immédiatement:

protected void Application_End()
{
    using (var flux = System.IO.File.CreateText(@"c:\temp\test2.txt"))
    {
        using (var client = new WebClient())
        {
            var url = "http://localhost/WebApplication2/";
            string hh = client.DownloadString(url);
            // c'est pour avoir une trace
            flux.WriteLine(hh);
        }
    }
}

Essayez cette fois de relancer le site et outre le fichier test2.txt, on voit réapparaître test.txt.

 

Le problème avec cette méthode est que parfois les écrans que l’on souhaite appeler pour la chauffe sont protégés par un logon/mot de passe. Il existe alors une autre possibilité consistant à écrire un fournisseur de chauffe avec l’interface System.Web.Hosting.IProcessHostPreloadClient. Cette interface peut être implémentée dans un type afin de le précharger dans une application ASP.NET.

Cette interface expose une méthode appelée Preload. Cette méthode sera appelée aussitôt que IIS aura redémarré et cela avant même que le premier visiteur du site aura activé Application_Start.

C’est donc un bon endroit où placer du code de chauffe ou du code pour signaler l’application à un load balancer.

 

Voici notre classe:

public class PreWarmCache : IProcessHostPreloadClient
{
    public void Preload(string[] parameters)
    {
        using (var flux = System.IO.File.CreateText(@"c:\temp\test.txt"))
        {
            flux.WriteLine("hello");
        }
    }
}

Ne cherchez pas, il n’existe aucun moyen d’injecter une valeur dans parameters. C’est un résidus non nettoyé d’une version béta.

 

Aller dans le gestionnaire IIS et sélectionner le nœud du serveur puis éditeur de configuration:

2014-09-20_21-49-05

 

Double cliquez sur Editeur de configuration.

2014-09-20_21-52-52

Dans la liste déroulante Section, choisir serviceAutoStartProvider. Ajoutez une déclaration vers votre fournisseur de chauffe:

2014-09-20_21-56-15

La syntaxe es:

  • le nom qualifié de la classe (avec son espace de noms)
  • virgule
  • nom de l’assemblage

L’exemple de code suivant vous donnera directement l’information que vous n’aurez plus qu’à copier:

Type type = typeof(PreWarmCache);
string name = type.AssemblyQualifiedName;

 

Cliquer sur ajouter pour enregistrer:

2014-09-20_21-57-49

Puis sur Appliquer.

On doit ensuite signaler au site web de lancer le fournisseur.

Toujours au même endroit on sélectionne la section sites:

2014-09-20_22-00-10

Cliquer sur collection pour ouvrir le formulaire:

2014-09-20_22-02-56

Sélectionnez votre site (le premier dans notre exemple) puis cliquer sur Collection:

2014-09-20_22-11-45

Puis sur Collection à nouveau et Ajouter:

2014-09-20_22-09-52

Faire ensuite Appliquer.

 

Bien entendu rien ne vous empêche d’éditer à la main le fichier ApplicationHost.config, c’est même la seule option avec les versions de IIS plus anciennes.

Tout d’abord la section <sites>:

2014-09-23_22-46-52

 

Le site est publié dans Default Web Site.

Il suffit de faire Redémarrer ou Arrêt puis Démarrer et on voit apparaître le fichier test.txt.

 

 

Le problème principal de cette méthode est que le code est difficile à tester car il est exécuté avant même que VS puisse s’attacher au processus. Il faut bien comprendre qu’il sera exécuté avant même Application_Start et donc avant que le site ait traité sa première requête. Vous ne pourrez donc pas y attacher un débogueur.

De plus s’il lève une exception ou si la configuration n’est pas correcte, rien ne démarrera.

 

Bibliographie

 

 

Publicités

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion / Changer )

Connexion à %s