Riciclo pool di app IIS + programmazione al quarzo

Sto eseguendo un’app Web su IIS 7.5 e deve essere riciclata occasionalmente (altrimenti l’utilizzo della memoria è fuori mano, qualcosa che sto esaminando!).

Quando ricicla, non funziona in modo efficace finché non arriva un’altra richiesta, che il quarzo non verrà eseguito.

C’è un modo per far sì che IIS attivi automaticamente 1 processo di lavoro subito dopo aver riciclato il pool di app per garantire che il quarzo sia sempre online?

Sì!

http://weblogs.asp.net/scottgu/archive/2009/09/15/auto-start-asp-net-applications-vs-2010-and-net-4-0-series.aspx lo descrive abbastanza bene, fondamentalmente è necessario:

  1. Modifica C: \ Windows \ System32 \ inetsrv \ config \ applicationHost.config per includere:

       
  2. Dichiara ciò che dovrebbe essere eseguito come “riscaldamento” per il tuo sito

             
  3. Configura la tua applicazione con qualsiasi logica di “riscaldamento” che desideri:

     public class PreWarmCache : System.Web.Hosting.IProcessHostPreloadClient { public void Preload(string[] parameters) { // Perform initialization and cache loading logic here... } } 

Nota: se tutto ciò di cui si ha bisogno è che il processo w3wp.exe sia presente, credo che sia necessario solo il passaggio 1. Se hai bisogno anche di altri elementi (come certe cose da caricare in memoria), si utilizzeranno anche i passaggi 2 e 3.

A partire da IIS 8.0, esiste un’opzione per simulare una richiesta alla pagina radice, quindi un’inizializzazione completa dell’applicazione: Impostazioni avanzate del pool di applicazioni -> Precarico abilitato = true.

Ovviamente, startMode dovrebbe essere AlwaysRunning.

Maggiori dettagli su come abilitare questa funzione possono essere trovati qui .

Ho preso una crepa a questo problema. Mentre la risposta di Stephen manterrà l’app in esecuzione, in un ambiente Spring.Net, il framework non parte e Quartz non verrà eseguito. Ho messo insieme un’implementazione di IProcessHostPreloadClient che farà partire una richiesta reale all’applicazione per far funzionare tutto il macchinario. Anche questo è pubblicato sul mio blog :

 public class Preloader : System.Web.Hosting.IProcessHostPreloadClient { public void Preload(string[] parameters) { var uris = System.Configuration.ConfigurationManager .AppSettings["AdditionalStartupUris"]; StartupApplication(AllUris(uris)); } public void StartupApplication(IEnumerable uris) { new System.Threading.Thread(o => { System.Threading.Thread.Sleep(500); foreach (var uri in (IEnumerable)o) { var client = new System.Net.WebClient(); client.DownloadStringAsync(uris.First()); } }).Start(uris); } public IEnumerable AllUris(string userConfiguration) { if (userConfiguration == null) return GuessedUris(); return AllUris(userConfiguration.Split(' ')).Union(GuessedUris()); } private IEnumerable GuessedUris() { string path = System.Web.HttpRuntime.AppDomainAppVirtualPath; if (path != null) yield return new Uri("http://localhost" + path); } private IEnumerable AllUris(params string[] configurationParts) { return configurationParts .Select(p => ParseConfiguration(p)) .Where(p => p.Item1) .Select(p => ToUri(p.Item2)) .Where(u => u != null); } private Uri ToUri(string value) { try { return new Uri(value); } catch (UriFormatException) { return null; } } private Tuple ParseConfiguration(string part) { return new Tuple(IsRelevant(part), ParsePart(part)); } private string ParsePart(string part) { // We expect IPv4 or MachineName followed by | var portions = part.Split('|'); return portions.Last(); } private bool IsRelevant(string part) { var portions = part.Split('|'); return portions.Count() == 1 || portions[0] == System.Environment.MachineName || HostIpAddresses().Any(a => a == portions[0]); } private IEnumerable HostIpAddresses() { var adaptors = System.Net.NetworkInformation .NetworkInterface.GetAllNetworkInterfaces(); return adaptors .Where(a => a.OperationalStatus == System.Net.NetworkInformation.OperationalStatus.Up) .SelectMany(a => a.GetIPProperties().UnicastAddresses) .Where(a => a.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork) .Select(a => a.Address.ToString()); } } 

Oppure puoi semplicemente modificare il metodo “Application_Start” in Global.asax per assicurarti che Quortz sia in esecuzione.