ASP.NET: La primera llamada a la aplicación tarda tanto que aparecen timeouts

Hace unos días me comentaron que las peticiones a una aplicación daban timeouts cuando se la invocaba por primera vez o cuando no había recibido peticiones durante un tiempo.

Hasta cierto punto, este comportamiento puede ser el esperado. Como ya os comenté en el post https://blogs.msdn.com/b/desarrolloweb/archive/2012/05/04/errores-compilacion-dinamica-aspnet.aspx, la primera vez que se invoca a una aplicación, se compila y se carga en memoria. Lo que puede producir una demora en la carga, y si la aplicación es lo suficientemente grande, que se produzca un timeout.

- La primera vez que carga

Cuando se invoca a una aplicación que no está en ejecución el IIS (para simplificar vamos a suponer que el ente “IIS” hace todas estas operaciones) inicia el w3wp.exe asociado al Application Pool de la aplicación si no está ejecutándose y carga la aplicación en su Application Domain.

- Cuando la aplicación lleva un tiempo sin peticiones

Ya sabemos el motivo por el que tarda la primera carga, pero ¿por qué tarda cuando la aplicación lleva un tiempo sin recibir peticiones?. Pues es posible que ocurra exactamente lo mismo que cuando es una carga inicial. Ahora la pregunta es ¿cómo puede ser si la aplicación ya se ha cargado?. Muy sencillo, si el IIS detecta
que un w3wp.exe ha superado el límite de tiempo inactivo (por defecto son 20 minutos) lo cierra, por lo que nuestra aplicación dejaría de estar ejecutándose y volveríamos a la primera situación.

- Troubleshooting

Vale, ahora que ya sé qué puede estar pasando, ¿cómo lo soluciono?. Esta parte es más complicada, ya que la lentitud en la carga puede darse por muchas razones.  Lo primero que revisaría es lo que comenté en el post de la compilación dinámica:

  • Deshabilitar el modo debug y batch: <compilation debug="false" batch="false" />
  • Publicar siempre la aplicación desmarcando la opción Allow this precompiled site to be updatable.
  • Revisar el código de la aplicación por si está realizando una carga inicial muy pesada que no sea necesaria

Si ya habéis probado estas opciones o no pueden realizarse por otros motivos, existe una solución menos elegante que es la de desactivar el timeout de inactividad y programar un reciclado en horas de baja carga.

  • IIS 6

Damos con botón derecho al Application Pool y seleccionamos propiedades. En la pestaña de Recycling marcamos la opción de Recycle worker processes at the followin times y añadimos las horas a las que queremos que se recicle automáticamente el proceso, en este ejemplo hemos puesto que sea a las 03:00.

image

En la pestaña de Performance desmarcamos la opción de Shutdown worker processes after being idle for

image

  • IIS 7.x

Para realizar la operación en IIS 7.x, debemos hacer clic con botón derecho en el Application Pool y elegir Advanced Settings.

Dentro del apartado Process Model, cambiamos el valor de Idle time-out (minutes) poniendo un 0 y en el apartado Recycling introducimos las horas deseadas (en este caso las 03:00) en el campo Specific Times

image

Espero que os sirva de ayuda

- José Ortega Gutiérrez