Optimizar trafico en JSON


Problema

Frecuentemente al realizar llamadas ajax a servicios se retorna un objeto JSON. Para resultados complejos es ideal debido a la facilidad y a lo practico que resulta estructurar la información. Pero en este caso el principal problema es el espacio/tamaño que ocupa la respuesta. Esto es debido a que el resultado se retorna al navegador cliente como texto plano. El tiempo de transmisión de la información es más elevado del realmente necesario. Pero es posible optimizar la respuesta; dado que los navegadores son capaces de aceptar peticiones comprimidas (gzip,deflate…). Al aplicar la compresión se obtiene un reducción del 88% del tamaño de la respuesta (al menos en mi caso).

Propuesta

En IIS tenemos la capacidad de habilitar la compresión para las respuestas JSON. Adjunto enlace Como habilitar compresión en IIS.
Pero en muchos casos no tenemos los privilegios para habilitar la compresión o no queremos habilitarlo en general.

Solución:

La propuesta consiste en crear un filtro de Acción de MVC (ActionFilterAttribute).
Para aplicarlo solo faltaría añadir el atributo CompressFilter a nuestra acción; como en el ejemplo adjunto. Lo aplicaríamos en las acciones que retornen JSON y queramos realizar compresión del mismo.

[CompressFilter]
public JsonResult QueryReturn(QueryParameter p)
{
...
}

El código del atributo filtro es el siguiente:

using System.Web;
using System.Web.Mvc;
using System.IO.Compression;

namespace Infrastructure.Compress
{

 public class CompressFilter : ActionFilterAttribute
 {
  public override void OnActionExecuting(ActionExecutingContext filterContext)
  {
   var request = filterContext.HttpContext.Request;
   var acceptEncoding = request.Headers["Accept-Encoding"];
   if (string.IsNullOrEmpty(acceptEncoding)) return;
   acceptEncoding = acceptEncoding.ToLowerInvariant();

   var response = filterContext.HttpContext.Response;

   if (acceptEncoding.Contains("deflate") || acceptEncoding == "*")
   {
     response.AppendHeader("Content-encoding", "deflate");
     response.Filter = new DeflateStream(response.Filter, CompressionMode.Compress);
   }
   else if (acceptEncoding.Contains("gzip"))
   {
     response.AppendHeader("Content-encoding", "gzip");
     response.Filter = new GZipStream(response.Filter, CompressionMode.Compress);
   }
  }
 }
}

Notas

Se da más prioridad a la compresión deflate sobre gzip. Deflate es menos intensa en recursos de servidor (40% menos).

Anuncios
Esta entrada fue publicada en Desarrollo y etiquetada , , . Guarda el enlace permanente.

2 respuestas a Optimizar trafico en JSON

  1. Abril dijo:

    Muy interesante.
    ¿Como usariamos el resultado desde js con JQuery?
    ¿Que proceso hemos de realizar?

    • Rodrigo Perez Burgues dijo:

      ¿Como usariamos el resultado desde js con JQuery?
      Desde JQuery es transparente, no se ha de hacer nada (queda en la capa de HTTP).
      ¿Que proceso hemos de realizar?
      Úsalo cuando el objeto JSON de retorno tenga gran tamaño. Por ejemplo respuestas de 100Kb.

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s