martes, 19 de febrero de 2013

Compresión HTTP

Habilitar la compresión de ficheros en el servidor antes de ser enviados al explorador, puede suponer una notable mejora del ancho de banda utilizado por tu aplicación. La idea es sencilla, si el explorador es capaz de entender un fichero comprimido, el servidor lo comprimirá antes de enviarlo por la red y después el explorador lo descomprimirá cuando lo reciba.

Un navegador indica al servidor que soporta la compresión a través de la cabecera Accept-Encoding. En esta cabecera se listan los modos de compresión que acepta el navegador. Normalmente tendrá un valor similar a gzip,deflate. Es decir, el navegador aceptará contenido comprimido desde el servidor con gzip o con deflate.

En cuanto al servidor, deberá tener activada la compresión y cuando un cliente envíe la cabecera Accept-Encoding con un valor válido, comprimirá el fichero antes de servírselo al cliente.

El servidor (hablando siempre en términos de IIS) diferencia entre contenido estático y dinámico. Comprimir el contenido estático no incurre (o casi no incurre) en ningún gasto de procesador para el servidor, puesto que lo comprimirá la primera vez que algún cliente lo solicite y después lo servirá ya comprimido a siguientes clientes desde una cache temporal. Por otro lado, si hablamos de contenido dinámico, aquí sí se advierte que comprimirlo supondrá un esfuerzo extra para el servidor puesto que no podrá cachear el recurso y siempre que un cliente lo solicite tendrá que comprimirse de nuevo antes de ser enviado (fijarse que un recurso típico dinámico podría ser una página .aspx que para cada solicitud podría devolver resultados distintos, es por ello que no puede ser cacheada).

Para habilitar la compresión en IIS 6.0, podremos realizar parte del trabajo desde la interfaz gráfica (inetmgr) pero para otra parte tendremos que utilizar el comando adsutil.vbs disponible en la carpeta AdminScripts.

Desde la interfaz gráfica podremos habilitar o deshabilitar la compresión estática y dinámica, así como establecer el directorio donde se cacheará los ficheros estáticos y, opcionalmente, poner un límite de tamaño a este directorio. Para ello hay que abrir la opción “Properties” en el nodo “Web Sites”. Todo esto está muy bien explicado en el siguiente enlace: Enabling HTTP Compression (IIS 6.0).

Services

El momento en el que tendremos que utilizar adsutil.vbs es a la hora de configurar que extensiones de ficheros son considerados estáticos y cuales dinámicos. Customizing the File Types IIS Compresses (IIS 6.0). Aunque en el anterior enlace está todo muy bien explicado, personalmente he encontrado problemas con la sintaxis propuesta para agregar las extensiones. La clave está en que el separador de extensiones (diga lo diga el anterior enlace) es CR/LF y no un blanco como dice la MSDN. A continuación te dejo un par de enlaces que aportan mucha luz a posibles problemas que podrían surgir al habilitar la compresión:

Troubleshooting HTTP Compression in IIS 6.0

HTTP Compression and IIS 6.0

Por otro lado, si eres un valiente (y quizás también un temerario), podrías editar directamente la metabase de IIS 6.0 para realizar los cambios oportunos. La metabase está en C:\WINDOWS\system32\inetsrv\MetaBase.xml. Por ejemplo la sección dedicada a la compresión podría ser como la siguiente:

<IIsCompressionScheme    Location ="/LM/W3SVC/Filters/Compression/deflate"
        HcCompressionDll="%windir%\system32\inetsrv\gzip.dll"
        HcCreateFlags="0"
        HcDoDynamicCompression="TRUE"
        HcDoOnDemandCompression="TRUE"
        HcDoStaticCompression="TRUE"
        HcDynamicCompressionLevel="0"
        HcFileExtensions="png
            jpg
            htm
            html
            css
            js
            txt"
        HcOnDemandCompLevel="10"
        HcPriority="1"
        HcScriptFileExtensions="asp
            dll
            exe
            aspx
            png
            jpg
            js"
    >
</IIsCompressionScheme>
<IIsCompressionScheme    Location ="/LM/W3SVC/Filters/Compression/gzip"
        HcCompressionDll="%windir%\system32\inetsrv\gzip.dll"
        HcCreateFlags="1"
        HcDoDynamicCompression="TRUE"
        HcDoOnDemandCompression="TRUE"
        HcDoStaticCompression="TRUE"
        HcDynamicCompressionLevel="0"
        HcFileExtensions="png
            jpg
            htm
            html
            css
            js
            txt"
        HcOnDemandCompLevel="10"
        HcPriority="1"
        HcScriptFileExtensions="asp
            dll
            exe
            aspx
            png
            jpg
            js"
    >
</IIsCompressionScheme>



Fíjate que las extensiones están separadas por un retorno de carro y que se configuran gzip y deflate de forma separada. Además puedes observar que algunas extensiones como jpg y png están incluidas tanto como contenido estático como dinámico. Esto es porque podría pasar que ASP.NET procesara este tipo de ficheros en algún momento y entonces pasarían a ser considerados dinámicos en vez de estáticos.


Si damos el salto a IIS 7.x o superior, lo cierto es que todo resultará ser más sencillo y, sobre todo más configurable. La principal diferencia es que en IIS 6.0 hablábamos de extensiones de ficheros y en IIS 7.x o superior, hablamos de tipos mime. Además, ahora podremos configurar la compresión directamente desde el fichero web.config de nuestra aplicación, desde la sección system.WebServer:


<urlCompression doDynamicCompression="true" doStaticCompression="true" />


Si queremos ampliar información sobre este elemento o sobre que tipos mime serán comprimidos, podemos navegar a los siguientes enlaces:


URL Compression


HTTP Compression


Lo cierto es que a medida que dispongamos de nuevos tipos mime, tendremos que ir actualizando la lista para tenerlos en cuenta, un ejemplo en Enabling dynamic compression (gzip, deflate) for WCF Data Feeds, OData and other custom services in IIS7


Un saludo!