Tutorial: Almacenamiento en caché de salida de IIS 7.0
por Saad Ladki
El contenido web se puede dividir en dos categorías: contenido estático y contenido dinámico. El contenido estático no cambia de solicitud a solicitud. El contenido que se devuelve al explorador web siempre es el mismo. Algunos ejemplos de contenido estático incluyen archivos HTML, JPG o GIF.
El otro es contenido dinámico. Esta es la respuesta que se genera para los cambios de contenido dinámico con cada solicitud. Algunos ejemplos son ASP.NET o contenido PHP.
Hay un gran intervalo entre estas dos categorías, que incluye el contenido semidinámico. Imagine una página ASP.NET dinámica que ejecuta una consulta de base de datos. No hay ninguna razón para ejecutar esta consulta en cada solicitud si las tablas de base de datos subyacentes cambian con poca frecuencia.
La característica de almacenamiento en caché de salida de IIS tiene como destino el contenido semidinámico. Permite almacenar en caché las respuestas estáticas para las solicitudes dinámicas y obtener una gran escalabilidad.
Requisitos previos
Para este tutorial, necesita IIS 7.0 o posterior en Windows® Vista SP1 o en Windows Server® 2008 Beta 3 o posterior. En este tutorial también se usa ASP.NET 2.0, que debe instalarse como componente opcional en la instalación de IIS.
Introducción al tutorial
En el siguiente tutorial, usamos las interfaces de extensibilidad de IIS para agregar mensajes de propiedad intelectual específicos del idioma a archivos JPG.
En primer lugar, lo hacemos agregando un controlador administrado. La inserción dinámica de un mensaje de propiedad intelectual en cada archivo JPG conlleva un costo, ya que ahora el código administrado debe ejecutarse para cada archivo JPG.
A continuación, instalamos WCAT, una herramienta de análisis de rendimiento de IIS, para medir el rendimiento de nuestro controlador de propiedad intelectual de JPG.
A continuación, agregamos almacenamiento en caché de salida para recuperar la degradación del rendimiento en la que se incurre mediante la adición de nuestro controlador de derechos de autor.
Parte I: Escritura y configuración del controlador de derechos de autor
Cree un directorio denominado "imágenes" en el directorio
%systemroot%\inetpub\wwwroot
. Ejecute el siguiente comando en un shell de comandos con privilegios elevados:md %systemdrive%\inetpub\wwwroot\pictures
Copie algunas imágenes digitales (en este tutorial, se supone que son archivos JPG) en el nuevo directorio de imágenes.
Nota:
Debido a la alta configuración de seguridad de Internet Explorer en Windows Server 2008, es posible que obtenga un cuadro de diálogo de seguridad que le indique que el sitio web está bloqueado. Para descargar el fondo de pantalla de IIS, agregue wallpaper.iis7.org a la lista de sitios de confianza.
Cree una aplicación con la herramienta de línea de comandos appcmd.
%windir%\system32\inetsrv\appcmd add app -site.name:"Default Web Site" -path:/pictures -physicalPath:%systemdrive%\inetpub\wwwroot\pictures
Cree el directorio App_Code debajo del directorio de imágenes:
md %systemdrive%\inetpub\wwwroot\pictures\App_Code
Abra el Bloc de notas y pegue el código siguiente en él.
using System; using System.Web; using System.Drawing; using System.Drawing.Imaging; namespace IIS7Demos { public class imageCopyrightHandler : IHttpHandler { public void ProcessRequest(HttpContext context) { string message = "Copyright © IIS 7.0 Team"; try { string languageHeader; languageHeader = context.Request.Headers["Accept-Language"].Substring(0,2).ToUpper(); switch (languageHeader) { case ("DE"): message = "IIS 7.0 Team - Alle Rechte vorbehalten"; break; case ("ES"): message = "Marca Registrada IIS 7.0 Team"; break; default: break; } } catch { // if something fails, e.g. no Language-Accept header, we go with the english message } InsertCopyrightMessage ( context, message, "yellow" ); } void InsertCopyrightMessage( HttpContext context, string message, string color ) { try { // get physical path of request string strPath = context.Request.PhysicalPath; // load as bitmap Bitmap jpgFile = new Bitmap(strPath); // add copyright message Graphics g = Graphics.FromImage(jpgFile); Font f = new Font("Arial", 20, GraphicsUnit.Pixel); SolidBrush sb = new SolidBrush(Color.FromName(color)); // write copyright message to bitmap g.DrawString( message, f, sb, 5, jpgFile.Height - f.Height - 5 ); f.Dispose(); g.Dispose(); // save it to response stream jpgFile.Save( context.Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg ); jpgFile.Dispose(); } catch (Exception e) { context.Response.Write(e.Message); } } public bool IsReusable { get { return true; } } } }
Guarde el archivo como
%systemdrive%\inetpub\wwwroot\pictures\App\_Code\imageCopyrightHandler.cs
.Cree el controlador que ejecuta este código cuando se solicita un archivo JPG:
%windir%\system32\inetsrv\appcmd set config /section:system.webServer/handlers /+[name='imageCopyrightHandler-Integrated',path='*.jpg', verb='GET,HEAD',type='IIS7Demos.imageCopyrightHandler',preCondition='integratedMode']
También debemos habilitar el examen de directorios porque aún no hay un documento predeterminado:
%windir%\system32\inetsrv\appcmd set config "Default Web Site/pictures" -section:directoryBrowse -enabled:true
Vaya a la aplicación de imágenes escribiendo lo siguiente en la barra de direcciones de Internet Explorer:
http://localhost/pictures
. Haga clic en el vínculo al archivo JPG en la lista de directorios de IIS. Debería ver la imagen JPG con el mensaje de propiedad intelectual insertado.Examine el código. Verá que el mensaje de propiedad intelectual depende del encabezado "Accept-Language" que envía el explorador. Si tiene instalada una versión alemana de Microsoft Server 2008, verá el mensaje de propiedad intelectual "IIS 7.0 Team - Alle Rechte vorbehalten"; si tiene una versión en español, verá "Marca Registrada IIS 7.0 Team". En todos los demás casos, el mensaje de propiedad intelectual será "Copyright © IIS 7.0 Team". Una manera de probar este código es cambiar el encabezado "Accept-Language" que Internet Explorer envía:
- Abra “Internet Explorer”.
- Abra el menú “Herramientas” y haga clic en “Opciones de Internet”.
- Haga clic en el botón "Idiomas".
- Haga clic en el botón "Agregar..." y agregue "es" para español o "de" para alemán.
- Mueva el nuevo idioma a la parte superior de la lista a través del botón "Subir".
- Vaya a
http://localhost/pictures/<your_jpg_file>.jpg
. El mensaje de propiedad intelectual ha cambiado al idioma que configuró. - No olvide volver al cuadro de diálogo "Idiomas" y restablecerlo; de lo contrario, podría preguntarse más adelante por qué obtiene páginas web españolas o alemanas.
Parte II: prueba de rendimiento de imageCopyrightHandler
Una vez que el controlador de derechos de autor JPG funciona, debemos determinar lo rápido que es nuestro código. Instale una Herramienta de kit de recursos de IIS 6.0 para ejecutar pruebas de rendimiento:
Descargue las Herramientas del kit de recursos de IIS 6.0 e instálelas. Realice una instalación personalizada e instale solo la Herramienta de análisis de capacidad web (WCAT). WCAT es la única característica de las Herramientas del kit de recursos de IIS 6.0 que necesitamos para realizar nuestras pruebas de rendimiento.
Nota:
Debido a la alta configuración de seguridad de Internet Explorer en Windows Server 2008, es posible que obtenga un cuadro de diálogo de seguridad que le indique que el sitio web está bloqueado. Para descargar el Kit de recursos de IIS 6.0, agregue *.microsoft.com a la lista de sitios de confianza.
Cree un directorio denominado PERFTEST, por ejemplo:
md %systemdrive%\perftest
El controlador WCAT requiere tres archivos de entrada:
- Un archivo de script que indica a WCAT qué direcciones URL solicitar. Cada dirección URL obtiene un ClassID único
- Un archivo de distribución que indica a WCAT cómo se deben distribuir las solicitudes entre las direcciones URL especificadas en el archivo de script
- Un archivo de configuración que configura los parámetros de una ejecución de rendimiento determinada, por ejemplo, la duración de las pruebas, el número de clientes HTTP que se van a simular, etc.
El archivo de script
Cree un nuevo archivo denominado script.cfg en el directorio perftest y pegue el siguiente contenido en él:
NEW TRANSACTION classId = 1 NEW REQUEST HTTP Verb = "GET" URL = "http://localhost/pictures/<your image name>.JPG" NEW TRANSACTION classId = 2 NEW REQUEST HTTP Verb = "GET" URL = "http://localhost/pictures/<your image name>.JPG"
Nota:
Reemplace la entrada de <nombre de la imagen> por los nombres de los archivos JPG. Si tiene más archivos JPG, puede agregar una nueva transacción. Asegúrese de asignar a cada transacción un nuevo ClassID.
El archivo de distribución
El archivo de distribución indica a WCAT cómo debe pesar las solicitudes. Con las dos direcciones URL anteriores, realizamos una distribución uniforme 50/50. Cada ClassID se solicita el 50 % del tiempo.
Cree un archivo denominado
%systemdrive%\perftest\distribution.cfg
en el directorio perftest y pegue el siguiente contenido en él:1 50 2 50
El archivo de configuración
Estos son los parámetros recomendados para la prueba:
- Duración: 30 segundos
- Preparación: 5 segundos
- Recuperación: 5 segundos
- Clientes HTTP simulados: 20
Cree un archivo denominado config.cfg en el directorio perftest y pegue el siguiente contenido en él:
Warmuptime 5s Duration 30s CooldownTime 5s NumClientMachines 1 NumClientThreads 20
Inicie el controlador ejecutando los siguientes comandos:
Cd \perftest "%programfiles%\IIS Resources\WCAT Controller\wcctl" -c config.cfg -s script.cfg -d distribution.cfg -a localhost
En cuanto todos los clientes estén conectados, se iniciará la prueba de rendimiento.
Dado que solo tenemos un cliente, abra otro shell de comandos con privilegios elevados y ejecute lo siguiente:
"%programfiles%\IIS Resources\WCAT Client\wcclient.exe" localhost
Para hacer esto con más clientes, establezca NumClientMachines en config.cfg en un número mayor y conecte los clientes al controlador a través del comando wcclient especificando el nombre de la máquina controladora.
Ejemplo: wcclient MyPerfTestControllerMachine
Nota:
Si hace esto en una versión de 64 bits de Windows, WCAT se instala en el directorio "archivos de aplicación (x86)" y debe usar
%programfiles(x86)%
para iniciar WCAT.Estos son los resultados de la primera ejecución:
######################################################################## WCAT Performance Statistics_________________________________ Server : localhost () #Transactions : 3 (HTTP/1.1) Total Async Sockets : 20 (5 WCAT Pool Threads) Total Elapsed Time : 30 Secs (0 Hrs,0 Mins,30 Secs) Current Connections : 20 Total Connection Attempts : 436 ( 14/Sec) Total Connect Errors : 0 ( 0/Sec) Total Success Connections : 436 ( 14/Sec) Total Consec. Connect Errors: 0 ( 0/Sec) Total Bytes : 32301100 ( 1051 KB/Sec) Total Bytes Written : 32264 ( 1 KB/Sec) Total Bytes Read : 32268836 ( 1050 KB/Sec) Total Requests : 436 ( 14/Sec) Total Responses : 436 ( 14/Sec) Total Socket Reads : 6976 ( 232/Sec) Total Socket Writes : 436 ( 14/Sec) Total Parse Errors : 0 ( 0/Sec) Total Socket Errors : 0 ( 0/Sec) Total I/O Errors : 0 ( 0/Sec) Total Internal Errors : 0 ( 0/Sec) Total Time Outs : 0 ( 0/Sec) Total 200 OK : 436 ( 14/Sec) Total 30X Redirect : 0 ( 0/Sec) Total 304 Not Modified : 0 ( 0/Sec) Total 404 Not Found : 0 ( 0/Sec) Total 500 Server Error : 0 ( 0/Sec) Total Bad Status : 0 ( 0/Sec) Min. Connect Time : 0 MS Avg. Connect Time : 0 MS Max. Connect Time : 16 MS Min. Resp Time (1st Byte) : 1281 MS Avg. Resp Time (1st Byte) : 1371 MS Max. Resp Time (1st Byte) : 1578 MS Min. Response Time (Last) : 1281 MS Avg. Response Time (Last) : 1373 MS Max. Response Time (Last) : 1578 MS Current Outstanding Connects: 0 ( 20 Max) Current Waitable Connects : 0 ( 20 Max) Total Asynchronous Connects : 531 ( 1/Sec) Total Discarded Connects : 0 ( 0/Sec) ########################################################################
El número importante que se va a examinar es el valor de solicitudes por segundo. En este caso, obtenemos 14 solicitudes por segundo.
Una pequeña advertencia: cuanto más grandes sean sus archivos JPG, menos solicitudes verá. Es probable que la máquina esté enlazada a la red: IIS no podrá controlar más solicitudes porque la red está saturada con los datos que está enviando. Verá los mejores resultados con archivos JPG en el intervalo de 200-300 KB.
Adición del almacenamiento en caché de salida
El código para insertar dinámicamente el mensaje de propiedad intelectual es bastante lento. Catorce solicitudes por segundo no es lo suficientemente rápido para un servidor web. IIS funciona mucho mejor. Todo lo que debe hacer es crear una directiva de almacenamiento en caché que coloque las direcciones URL con la extensión JPG en la caché del modo kernel. Aquí se muestra cómo agregar la directiva de caché:
Adición de una directiva de caché a través de la herramienta de administración de IIS
- Vaya a "Herramientas administrativas" y seleccione "Administrador de Internet Information Services (IIS).
- Use la vista de árbol en el lado izquierdo para ir a la aplicación "imágenes".
- Seleccione el elemento de menú "Reglas de almacenamiento en caché de salida".
- Haga clic en "Agregar..." en el menú "Acciones".
- Agregue JPG como la "Extensión de archivo" para almacenar en caché.
- Seleccione "A intervalos de tiempo" en la sección "Supervisar archivos almacenados en caché" y escriba 00:00:10 como intervalo de tiempo.
- Active la casilla "Encabezados" y escriba "Accept-Language".
Nota:
La interfaz de usuario de caché de salida no está disponible en versiones anteriores a Windows Vista Service Pack 1.
Agregar una directiva de caché a través de la línea de comandos
Para realizar el mismo procedimiento con la herramienta appcmd, escriba el siguiente comando:
%windir%\system32\inetsrv\appcmd set config "Default Web Site/pictures"
-section:caching /+profiles.[extension='.jpg',duration='00:00:10',
policy='CacheForTimePeriod',varyByHeaders='Accept-Language']
Repita la ejecución de rendimiento para ver qué cambian las opciones de configuración y cómo cambian.
Inicie el controlador ejecutando los siguientes comandos:
Cd \perftest "%programfiles%\IIS Resources\WCAT Controller\wcctl" -c config.cfg -s script.cfg -d distribution.cfg -a localhost
Inicie el cliente con lo siguiente:
"%programfiles%\IIS Resources\WCAT Client\wcclient.exe" localhost
Nota:
Si hace esto en una versión de 64 bits de Windows, WCAT se instala en el
program files (x86)
directorio y debe usar%programfiles(x86)%
para iniciar WCAT.
Salida de ejemplo
########################################################################
WCAT Performance Statistics_________________________________
Server : localhost ()
#Transactions : 3 (HTTP/1.1)
Total Async Sockets : 20 (5 WCAT Pool Threads)
Total Elapsed Time : 30 Secs (0 Hrs,0 Mins,30 Secs)
Current Connections : 19
Total Connection Attempts : 13020 ( 434/Sec)
Total Connect Errors : 0 ( 0/Sec)
Total Success Connections : 13019 ( 433/Sec)
Total Consec. Connect Errors: 0 ( 0/Sec)
Total Bytes : 958045737 (31186 KB/Sec)
Total Bytes Written : 963406 ( 31 KB/Sec)
Total Bytes Read : 957082331 (31155 KB/Sec)
Total Requests : 13019 ( 433/Sec)
Total Responses : 13019 ( 433/Sec)
Total Socket Reads : 258283 ( 8609/Sec)
Total Socket Writes : 13019 ( 433/Sec)
Total Parse Errors : 0 ( 0/Sec)
Total Socket Errors : 0 ( 0/Sec)
Total I/O Errors : 0 ( 0/Sec)
Total Internal Errors : 0 ( 0/Sec)
Total Time Outs : 0 ( 0/Sec)
Total 200 OK : 13019 ( 433/Sec)
Total 30X Redirect : 0 ( 0/Sec)
Total 304 Not Modified : 0 ( 0/Sec)
Total 404 Not Found : 0 ( 0/Sec)
Total 500 Server Error : 0 ( 0/Sec)
Total Bad Status : 0 ( 0/Sec)
Min. Connect Time : 0 MS
Avg. Connect Time : 0 MS
Max. Connect Time : 63 MS
Min. Resp Time (1st Byte) : 0 MS
Avg. Resp Time (1st Byte) : 33 MS
Max. Resp Time (1st Byte) : 125 MS
Min. Response Time (Last) : 0 MS
Avg. Response Time (Last) : 45 MS
Max. Response Time (Last) : 141 MS
Current Outstanding Connects: 0 ( 20 Max)
Current Waitable Connects : 0 ( 20 Max)
Total Asynchronous Connects : 14093 ( 147/Sec)
Total Discarded Connects : 0 ( 0/Sec)
########################################################################
Temas avanzados de almacenamiento en caché de salida
Contadores de rendimiento
Para determinar el rendimiento en la caché de salida, examine los contadores de caché de salida en el "Monitor de confiabilidad y rendimiento". Hay muchos contadores interesantes. Este es un ejemplo de cómo usar el "Monitor de confiabilidad y rendimiento" junto con la caché de salida.
- En Windows Server 2008, inicie PERFMON a través del menú Inicio. Vaya a "Herramientas administrativas" y haga clic en "Monitor de confiabilidad y rendimiento". En Vista, encontrará "Herramientas administrativas" en el Panel de control.
- Seleccione "Monitor de rendimiento" en la vista de árbol de la derecha y haga clic en el signo "+" en la barra de herramientas.
- Vaya al contador "Caché del servicio web" y haga clic en él para abrirlo.
- Agregue el contador "Tocal de URI almacenados en caché".
- Vuelva a ejecutar la prueba WCAT.
Verá que el número de URI almacenados en caché aumenta en función del número de elementos que solicite durante la prueba de rendimiento.
Reglas de almacenamiento en caché del modo kernel de IIS
La caché de salida de IIS admite dos directivas de caché. La directiva de caché de salida normal aprovecha una memoria caché que reside en un proceso de trabajo de IIS. La otra directiva de caché es una directiva de caché en modo kernel, en cuyo caso la caché reside en HTTP.SYS, un controlador modo kernel.
El almacenamiento en caché del contenido en modo kernel permite que el sitio web vaya más rápido. Modifique la configuración de la aplicación de imágenes para usar la caché en modo kernel. Este es el aspecto de la configuración actual (%systemdrive%\inetpub\wwwroot\pictures\web.config
):
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<directoryBrowse enabled="true" />
<caching>
<profiles>
<add extension=".jpg" policy="CacheForTimePeriod"
duration="00:00:10" varyByHeaders="Accept-Language" />
</profiles>
</caching>
</system.webServer>
</configuration>
Ahora cámbielo para usar el almacenamiento en caché en modo kernel:
Abra
%systemdrive%\inetpub\wwwroot\pictures\web.config
.Cambie el valor.
<caching> <profiles> <add extension=".jpg" policy="CacheForTimePeriod" duration="00:00:10" varyByHeaders="Accept-Language" /> </profiles> </caching>
por las siguientes:
<caching> <profiles> <add extension=".jpg" kernelCachePolicy="CacheForTimePeriod" duration="00:00:10" /> </profiles> </caching>
Verá que ya no usamos el atributo varyByHeaders. Esto se debe a que kernelModeCache no admite algunas de las características que admite la caché de salida del modo de usuario.
Limitaciones de la caché de salida del modo kernel
Hay dos diferencias significativas entre la memoria caché de salida de modo de usuario y de modo kernel.
- La caché de salida del modo kernel no admite módulos y características que deben ejecutarse en modo de usuario, como la autenticación o la autorización. Ejemplo: si se habilitan esquemas de autenticación como la autenticación básica o de Windows, la directiva de caché no funcionará. El contenido se sirve pero no se almacena en caché. Consulte "Solución de problemas de almacenamiento en caché" para ver cómo averiguar si el contenido se almacena en caché. Encontrará más detalles sobre por qué es posible que las respuestas no se almacenen en caché en modo kernel en este artículo de la Knowledge Base.
- La caché de salida del modo kernel admite el atributo varyByHeaders, pero no varyByQuerystring.
Solución de problemas de almacenamiento en caché
El almacenamiento en búfer de eventos de solicitud con error (FREB) es la mejor manera de averiguar si la solicitud se almacena en caché o no. FREB le indica por qué algo no se almacena en caché. Este es un ejemplo de un registro FREB. En este caso, el evento HTTPSYS_CACHEABLE le indica que la solicitud no se almacena en caché porque la caché en modo kernel no está habilitada.
Para obtener información más detallada sobre cómo trabajar con FREB, consulte Solución de problemas de solicitudes con errores mediante seguimiento en IIS 7.
Use el siguiente comando para averiguar qué contenido se almacena en caché en modo kernel:
netsh http show cachestate
Complejidades del almacenamiento en caché
Incluso si habilita el almacenamiento en caché de salida, IIS no almacena inmediatamente en caché una solicitud. Debe solicitarse varias veces antes de que IIS considere que una solicitud es "digna de la memoria caché". El merecimiento de la memoria caché se puede configurar a través de la sección ServerRuntime que se describe en este artículo de MSDN.
Las dos propiedades que determinan el merecimiento de la caché son frequentHitTimePeriod y frequentHitThreshold. Una solicitud solo se almacena en caché si llegan más de <frequentHitThreshold>
solicitudes de una dirección URL que se puede almacenar en caché dentro de <frequentHitTimePeriod>.
La configuración predeterminada para frequentHitTimePeriod es de 10 segundos.
La configuración predeterminada para frequentHitThreshold es 2.
Almacenamiento en caché de las páginas más populares
En el ejemplo anterior, colocamos todos los archivos con la extensión JPG en la caché de salida. Esto no siempre funciona porque a veces desea ser más selectivo y solo colocar un documento determinado en la memoria caché de salida. Aquí se muestra cómo hacer esto con la página solicitada con más frecuencia, el documento predeterminado:
Cree un archivo denominado default.aspx en el directorio
%systemdrive%\inetpub\wwwroot\pictures
y agregue el código siguiente:<%=DateTime.Now%>
Vaya a "Herramientas administrativas" y seleccione "Administrador de Internet Information Services (IIS).
Use la vista de árbol en el lado izquierdo para ir a la aplicación "imágenes".
Haga clic en "Vista de contenido" en la parte inferior de la página.
Seleccione el documento predeterminado, por ejemplo, la página default.aspx.
Haga clic en "Cambiar a la vista de características" en el menú "Acciones" de la derecha. Todas las opciones que configure ahora solo se aplicarán al documento predeterminado.
Abra la configuración "Reglas de almacenamiento en caché de salida".
Agregue ".aspx" como extensión de archivo.
Seleccione "almacenamiento en caché en modo kernel" y, a continuación, podemos seleccionar "En intervalos de tiempo" y habilitar "Supervisar archivos almacenados en caché" y escribir 00:00:30 como intervalo de tiempo.
Vaya a
http://localhost/pictures
con "Internet Explorer". Al actualizar constantemente la página (presione Ctrl + F5 para asegurarse de que no procede de la caché del explorador), verá que el tiempo no cambiará durante 30 segundos.
Resumen
El uso de la característica de almacenamiento en caché de salida de IIS para el contenido semidinámico puede mejorar el sitio web. Verá una mejora sustancial en el rendimiento y la capacidad de rendimiento. Un cambio de configuración simple es suficiente para aprovechar esta característica.