2009-11-03 7 views
9

Después de años de desarrollo de ASP.NET estoy bastante sorprendido de que no parezca encontrar una solución satisfactoria para esto.Mantener un sitio web ASP.NET IIS sensible cuando el tiempo entre visitas es largo

¿Por qué un sitio IIS ASP.NET parece siempre quedarse dormido (durante 2-6 segundos) después de un cierto tiempo de inactividad (después de varias horas), durante el cual no se envía respuesta HTTP de servidor a cliente. Esto sucede en cualquier tipo de sitio, una página o muchas, db o no, independientemente de la configuración. ¿Cómo puedo arreglar esto?

Durante el tiempo de espera, el servidor no está ocupado y no hay altos picos ni falta de memoria (.NET). Supongo que tiene que ver con Windows moviendo el proceso de IIS al fondo y su memoria al archivo de la página, pero no estoy seguro. Alguien alguna idea?

EDITAR: una solución es enviar alguna solicitud de HTTP una vez por hora más o menos, pero espero algo más constructivo.
EDITAR: lo que quise decir es: después de horas de inactividad, hace una pausa de varios segundos en cualquier nueva solicitud HTTP.

+0

+1, pero pertenece a serverfault. –

+0

¿Está compilando su sitio? Si no, te estás perdiendo algunas mejoras de rendimiento muy grandes. – codethrift

+0

@theminesgreg: los sitios se compilan, la depuración no está establecida, las optimizaciones están activadas para (cualquiera) dlls. @John: No estoy seguro de que pertenezca a serverfault, ya que esto realmente me molesta como programador, pero corrígeme si estoy equivocado – Abel

Respuesta

5

El tiempo de espera predeterminado para IIS es de 20 minutos. Lo que esto significa es que si su aplicación ASP.NET no recibe ninguna solicitud nueva durante 20 minutos, se cerrará el proceso de trabajo. Se puede tomar una cantidad considerable de tiempo para calentar el proceso de la nada - asambleas de carga en la memoria, la compilación previa, etc.

(Edición: he creado una clase de ayuda simple que resuelve el problema de tiempo de espera estándar - básicamente el la aplicación web "pincha" a sí misma de vez en cuando para mantener vivo el proceso. El enfoque ideal es cambiar la configuración en IIS, pero para los servidores donde esto no es posible, mi clase funciona bastante bien. - Código en la parte inferior)

Mientras el proceso de trabajo aún está activo, no se debe despriorizar. Ciertamente no tan rápido como estás describiendo. Es posible que pueda confiar en elementos almacenados en la memoria caché durante un período de tiempo muy breve, y se están cayendo cuando no se los solicitó durante más de unos segundos. Sin saber más sobre los detalles de su aplicación, es imposible decirlo.

Como siempre, perfilar su aplicación es la única forma de proporcionar información concreta. Usar un producto como ANTS lo ayudará a determinar en qué parte del código su aplicación está gastando más tiempo, para que pueda aislar dónde se produce el "bloqueo".

public class KeepAlive 
{ 
    private static KeepAlive instance; 
    private static object sync = new object(); 
    private string _applicationUrl; 
    private string _cacheKey; 

    private KeepAlive(string applicationUrl) 
    { 
     _applicationUrl = applicationUrl; 
     _cacheKey = Guid.NewGuid().ToString(); 
     instance = this; 
    } 

    public static bool IsKeepingAlive 
    { 
     get 
     { 
      lock (sync) 
      { 
       return instance != null; 
      } 
     } 
    } 

    public static void Start(string applicationUrl) 
    { 
     if(IsKeepingAlive) 
     { 
      return; 
     } 
     lock (sync) 
     { 
      instance = new KeepAlive(applicationUrl); 
      instance.Insert(); 
     } 
    } 

    public static void Stop() 
    { 
     lock (sync) 
     { 
      HttpRuntime.Cache.Remove(instance._cacheKey); 
      instance = null; 
     } 
    } 

    private void Callback(string key, object value, CacheItemRemovedReason reason) 
    { 
     if (reason == CacheItemRemovedReason.Expired) 
     { 
      FetchApplicationUr(); 
      Insert(); 
     } 
    } 

    private void Insert() 
    { 
     HttpRuntime.Cache.Add(_cacheKey, 
      this, 
      null, 
      Cache.NoAbsoluteExpiration, 
      new TimeSpan(0, 10, 0), 
      CacheItemPriority.Normal, 
      this.Callback); 
    } 

    private void FetchApplicationUrl() 
    { 
     try 
     { 
      HttpWebRequest request = HttpWebRequest.Create(this._applicationUrl) as HttpWebRequest; 
      using(HttpWebResponse response = request.GetResponse() as HttpWebResponse) 
      { 
       HttpStatusCode status = response.StatusCode; 
       //log status 
      } 
     } 
     catch (Exception ex) 
     { 
      //log exception 
     } 
    } 
} 

uso (tal vez en App_Start):

KeepAlive.Start("http://www.yoursite.com/"); 
+0

Señala algunos pensamientos interesantes. Siempre supuse que nunca llegó al 'Application_Start', pero qué sé, quizás llegue allí, cargue libs, etc., y luego se reanude. Tenga en cuenta que el tiempo no es de 20 minutos (tiempo de espera de sesión), se estrangula por un tiempo después de aproximadamente 3+ horas, pero no estoy seguro. El tiempo puede ser variable. No es solo "un sitio", es "todos los sitios" en muchos sistemas y versiones de IIS/Windows. Todos son .NET 3.5 sin embargo. – Abel

+0

Encendido * "pero qué sé" * >>> quería decir: debería iniciar sesión o activar Trace o lo que sea. Conozco ANTS, pero no estoy seguro de que pueda ayudar aquí: el bloqueo parece ocurrir antes de que se cargue algo, lo que incluiría ANTS. – Abel

+0

Acabo de notar el mismo comentario aquí http://www.eggheadcafe.com/software/aspnet/30548981/slow-site-startup.aspx, que menciona este tiempo de espera inactivo. No ocurre localmente, solo remotamente en configuraciones que no siempre administro. No debería tomar mucho tiempo para averiguar si todo está en este entorno. – Abel

1

Si está utilizando IIS 7 hay un plugin llamado Aplicación IIS Calentamiento del equipo IIS que le ayudará a mantener todo tostado

He escrito un blog post sobre mis experiencias al usarlo.

+1

Plugin interesante. Además, el tiempo de espera de 20 minutos se puede configurar en el grupo de aplicaciones. Configuré 24 horas en la mayoría de los servidores, lo que ayuda (PD: su sitio no responde ...) – Abel

+0

Hilarante: asumo que el blog estaba reconstruyendo jaja ... qué irónico – Doug

0

Si solo está compilando su código por el momento, entonces también puede consultar precompilando sus archivos aspx en el momento (en lugar del tiempo de ejecución, que es el predeterminado). Creo que esta compilación sobre la marcha es lo que ocupa la mayor parte del tiempo cuando se despierta un sitio inactivo de ASP.NET. Puede leer más al respecto here.

Actualización:

El grupo de aplicaciones es asesinado cuando se alcanza el valor IdleTime y salida exprés - el valor predeterminado es de 20 minutos (se puede cambiar este valor). ¿Estás seguro de que la interfaz de usuario no se vuelve a compilar después de reiniciar la aplicación en este caso? (No estoy seguro de si obliga a una UI a recompilarse o no).

+0

Si bien su afirmación es correcta, la compilación de páginas solo se realiza una vez , incluso si no elige precompilar (que prefiero si tengo algo que decir en un proyecto). El problema mencionado en la pregunta se produce después de 20 minutos de inactividad y podría considerarse el "modo de suspensión" del grupo de aplicaciones. Verifique sus registros si tiene un sitio web local pequeño: cuando los primeros clientes lleguen a las 4AM, verá un largo tiempo de espera para las primeras solicitudes. – Abel

+0

¿Qué versión de IIS estás usando? y ¿Tiene acceso de administrador a IIS? – UpTheCreek

Cuestiones relacionadas