Bricomanía: añadiendo caché a nuestros servicios WCF

Resulta que andaba yo el otro día, como loco, buscando el equivalente al parámetro CacheDuration del atributo WebMethod de ASP.Net en WCF. Resumiendo necesitaba algo que me permitiese establecer declarativamente, en tiempo de desarrollo, que las llamadas a una operación de un servicio WCF devolviesen un resultado cacheado y que este caducase cada cierto tiempo. Esta posibilidad que nos brinda ASP.Net nos permite mejorar muchísimo la escalabilidad de nuestros servicios evitando que lleguen hasta el almacen de datos peticiones de datos que cambiaban muy raramente o evitando que se ejecuten completamente operaciones que puedan ser costosas.


Después de buscar sin exito durante algún tiempo por la MSDN y algunos otros sitios el equivalente en WCF a la carácteristica que tanto me había ayudado cuando desarrollaba servicios con ASP.Net hice lo que siempre hago cuando la MSDN y Google me fallan, llamar a Unai (es conocido el mito de que Fraga se sabía la guia de teléfonos de Galicia de memoria y dicen también que hay otro que se sabe la MSDN). Unai certificó mis temores, no habia nada equivalente al CacheDuration en WCF.


Pero claro Unai, que en lo que a .Net se refiere es el equivalente al barbas de bricomanía, me dijo: tio, si no lo hay te lo haces, para algo WCF es extensible y flexible y un montón de cosas más…. ¿no?. ¿Alguna pista? le pregunte… y claro me dio la pista adecuada, vete a tu tienda de bricolage favorita y comprate un IOperationBehavior y un IOperationInvoker me dijo… y luego ya sabes la herramientas habituales, Visual Studio, WCF, un poco de AOP, lijar, pintar y pulir…


Pero claro, yo soy más de Ikea que de Leroy Merlin, así que me puse a buscar algo más ‘de montar’ que ‘de hacer’… y con la pista de Unai encontre un motón de implementaciones de lo que yo necesitaba…


Pero ya sabemos lo que pasa con Ikea, o te sobran piezas o te faltan o no encajan. Y en esta ocasión no iba a ser diferente. Las implementaciones de IOperationBehavior de caché para WCF que encontré o bien cascaban, o bien no funcionaban con invocaciones asíncronas, o el código era pésimo, o eran una simple prueba de concepto, o todo a la vez… así que tube que pasarme a la táctica ‘hágalo usted mismo’ y, después de enviarle el código a Unai para que me ‘desatascase’ de un error tonto, conseguí resultados. A continuación os comento un poco los fundamentos y el resutado.


Básicamente se trata de implementar un IOperationBehavior en forma de atributo que podemos aplicar a aquellas operaciones de nuestros servicios WCF que queremos que presenten el comportamiento de caché. He llamado a este behavior UseCache. A continuación os muestro el código necesario para aplicar el behavior en cuestión:



   [UseCache(5)]


   public DateTime GetDateTime()


   {



     return DateTime.Now;


   }


El código del IOperationBehavior no puede ser más simple, simplemente se trata de un atributo con una propiedad que establece durante cuanto tiempo se mantendrá cacheado el resultado. El único método que debemos implementar es ApplyDispatchBehavior para sustituir el Invoker estandar de WCF por mi CachedInvoker, que será la clase encargada de cachear los resultados.



  /// <summary>


  /// This attribute is used for adding cache to and WCF operation


  /// </summary>


  [AttributeUsage(AttributeTargets.Method)]


  sealed public class UseCacheAttribute : Attribute, IOperationBehavior


  {


    /// <summary>


    /// Constructor


    /// </summary>


    /// <param name=»cacheDuration»>


    /// The number of seconds the response should be held in the cache.


    /// </param>


    public UseCacheAttribute(int cacheDuration)


    {


      _cacheDuration = cacheDuration >= 0 ? cacheDuration : 0;


    }


 


    /// <summary>


    /// This method applies our operation invoker to the operation


    /// </summary>


    /// <param name=»operationDescription»>Operation description</param>


    /// <param name=»dispatchOperation»>Operation dispatch</param>


    /// <remarks>


    /// <see cref=»IOperationBehavior.ApplyDispatchBehavior»/>


    /// </remarks>


    public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)


    {


      dispatchOperation.Invoker = new CachedInvoker(dispatchOperation.Invoker, _cacheDuration, dispatchOperation.Name);


    }


  }


Una vez que aplicamos este behavior a las operaciones de nuestro servicios cualquier llamada a esa operación pasará a través de nuestro IOperationInvoker que utiliza la cache de ASP.Net para cachear el resultado de la invocación a la operación. Aprovecho para recordar que desde la versión 2 del Framework de .Net se puede usar la cache de ASP.Net en cualquier tipo de aplicación, WCF incluido, aunque esto no es cierto para 1.x. De esta manera, si el resultado ya existe para el valor de los parámetros pasados, se devuelve desde la caché cortocircuitando la llamada antes de que vaya más allá de la fachada de servicios. A continuación pongo el código más relevante del invoker:



  /// <summary>


  /// Operation invoker that adds caching capabilities


  /// </summary>


  public class CachedInvoker : IOperationInvoker


  {


    …


 


    /// <summary>


    /// Implementation for Invoke


    /// </summary>


    /// <param name=»instance»>Instance</param>


    /// <param name=»inputs»>Inputs</param>


    /// <param name=»outputs»>Outputs</param>


    /// <returns>An array of object</returns>


    /// <remarks>


    /// <see cref=»System.ServiceModel.Dispatcher.IOperationInvoker.Invoke»/>


    /// </remarks>


    public object Invoke(object instance, object[] inputs, out object[] outputs)


    {


      string key = GetCacheKey(_operationName, inputs);


      object result = HttpRuntime.Cache[key];


      if (result == null)


      {


        result = _innerInvoker.Invoke(instance, inputs, out outputs);


        HttpRuntime.Cache.Add(


          key, result, null, DateTime.Now.AddSeconds(_cacheDuration),


          System.Web.Caching.Cache.NoSlidingExpiration,


          CacheItemPriority.Default, null);


      }


      outputs = new object[0];


      return result;


    }




    /// <summary>


    /// Get a key for caching based on operation inputs and name.


    /// </summary>


    /// <param name=»inputs»>Inputs</param>


    /// <param name=»operationName»>Operation name</param>


    /// <returns>The key.</returns>


    private static string GetCacheKey(string operationName, object[] inputs)


    {


      string key = operationName;


      for (int i = 0; i < inputs.Length; i++)


      {


        key =  key + ‘$’ + inputs[i].ToString();


      }


      return key;


    }
    …



  }


Una vez aplicado el behavior UseCache a la operación de nuestro servicio las llamadas a esta se comenzarán a cachear. Podéis ver, en el pantallazo siguiente, el resultado de llamar a un método de un servicio que simplemente devuelve la hora actual cada medio segundo tras haberle aplicado el atributo [UseCache(5)].


LLamadas cacheadas


Podéis descargar el código con sus pruebas unitarias y una aplicación de consola de prueba.


En todo proyecto hay servicios que devuelven datos que cambian cada mucho tiempo. Los conceptos mostrados también serian de aplicación para implementar el mecanismo de caché con invalidación de la caché por dependencias usando CacheDependency o SqlCacheDependency, solo cambiarían las líneas que añaden el resultado de la operación a la caché. Espero que os resulte útil.

El milagro de los panes y los ‘teses’

Logo de Pex


Parece que hay una tendencia cada vez más marcada hacia asegurar la calidad del código fuente y del software mediante herramientas de automatización. Hace poco conocíamos la aparición de Microsoft Source Analysis for C# y de la mano de mi compañero Jose Luis Soria he tenido contacto recientemente con BDD (Behavior Driven Development), una nueva manera de escribir test unitarios realmente prometedora… hoy toca hablar de otra herramienta relacionada con las anteriores.


¿Os imagináis que existiese un software que fuese capaz de analizar un conjunto de pruebas parametrizadas escritas manualmente y a partir de este conjunto generar automáticamente un nuevo conjunto de pruebas con alta cobertura y que además prueban condiciones de frontera? ¿Os imagináis que además este software fuese capaz de indicarnos como corregir potenciales bugs?. Suena casi milagroso ¿no?. Pues bien, gracias a un grupo de investigadores de Microsoft Research, el milagro es posible y se llama Pex (Program EXploration): Automated Exploratory Testing for .Net. El primero que me hablo de esta herramienta fue Juanjo Olabarria uno de los habituales de Artalde y desde entonces he estado esperando con verdadero interés su primera release pública que finalmente se ha producido.


Su integración en el proceso de desarrollo es muy natural. El desarrollador escribe un conjunto de pruebas similares a pruebas unitarias pero que toman parámetros. Luego utilizaremos Pex (que está integrado con Visual Studio) para generar las pruebas unitarias y ejecutarlas. La siguente imagen resume el proceso:


Esquema de utilización de Pex 


La principal duda que me plantea esta herramienta es que al crecer muchísimo el número de pruebas unitarias, el tiempo de ejecución de las mismas se alarga. Y como todo desarrollador acostumbrado a usar pruebas unitarias sabe, la frecuencia con que se ejecutan los test unitarios depende de su velocidad y las pruebas que no se ejecutan frecuentemente son menos útiles que las que sí.


Estad atentos, en próximas entregas os comentaré mis primeras sensaciones con esta herramienta. Los más impacientes podéis ir viendo el screencast que ha publicado el equipo de Pex. Creo que se trata de una herramienta muy prometedora, que permite que con el mismo esfuerzo, lograr test unitarios más efectivos. Supongo que a futuro es algo que veremos integrado en Visual Studio Team System.

Operaciones asíncronas en proxies de WCF

Una de las interesantes novedades de Visual Studio 2008 en lo relavito a WCF es la posibilidad de seleccionar opciones avanzadas a la hora de generar los proxies de la lado cliente de nuestros servicios WCF. Entre estas opciones avanzadas, hay una que, desde mi punto de vista destaca sobre el resto. Más que nada porque es una característica con la que ya contabamos en los proxies de servicios web anteriores a WCF. Se trata de la generación de invocaciones asíncronas.

Para que nuestros proxies se generen con operaciones asíncronas, en el diálogo que se muestra para añadir un servicio, podemos pinchar en el botón de opciones avanzadas y veremos otro cuadro de diálogo que nos permite entre otras cuestiones (que en otras ocasiones trataré) la posibilidad de solicitar que nuestro proxies se generen con operaciones asíncronas.

 

Una vez hecho esto nuestros proxies contarán no solo con los típico método síncronos que nos permiten llamar a las operaciones de nuestro servicio, sin que además contaremos con métodos del estilo BeginMetodoDelServicio y EndMetodoDelServicio típico patrón de invocación asíncrona de la plataforma .Net.

image

Esto nos permitira que la llamadas a las operaciones de nuestro servicio no bloqueen nuestro cliente y que el hilo que realiza la invocación quede libre para realizar otras actividades (actualizar la interfaz de usuario típicamente). Además siempre podremos segir usando la versión síncrona del método.

Plain Flash 2008

Plain Flash 08 Cartel Este pasado fin de semana, en el idílico marco de las montañas Leonesas, exactamente en el lugar donde «cristo perdio el mechero» se ha celebrado el tercer Plain Flash. Evento en el que todos los miembros de Plain Concepts nos juntamos y compartimos un fin de semana de tecnología, aventura, descanso y compañerismo, en un marco incomparable (podéis ver el wallpaper oficial del evento, para haceros una idea).

Por la parte técnica hubo ponencias sobre System.Addins, Spring.net, Nuevas tendencias y reconocimiento de imageners, una introducción a Behavior Driven Development y una mesa redonde sobre leguajes de programación dinámicos. En definitiva todo Plain Concepts compartierndo conocimientos, intereses técnicos y chascarrillos informáticos varios.

Además en la parte lúdica los más atrevidos y menos frioleros se atrevieron con el descenso del barranco de Quincoajo, aunque se rumorea que lo más duro fue el ascenso y los menos intrepidos se enfrentaron a los terribles chorros y vapores del balneario de Caldas de Luna. Otro grupito aun más relajado si cabe nos dedicamos a dormir, pasear, charla, hacer una rutita en coche por las montañas y comer como unos señores.

Por el lado gastronómico nos pusimos hasta la cejas… ¡que bien se come en León!.

En defiitiva un divertidísimo fin de semana, en un paraje incomparable y con una compañia inigualable en lo técnico y lo humano. Que bien me lo pase… 🙂

Forzar la ejecución en 32 bits de aplicaciones .Net

Los sistemas de 64 bits están irrumpiendo cada vez con mayor fuerza. Hasta hace poco no era muy habitual el tener que despleguar una aplicación sobre 64 bits .Una de las grandes ventajas de .Net es que esta transición es en gran medida transparente. El compilador de .Net se encargará de compilar nuestra aplicación a 32 o 64 bits según sea la plaforma sobre la que la estamos ejecutando. Esto que sin duda es una gran ventaja sobre los lenguajes nativos pues nos permite no tener que compilar explicitamente una versión de 32 y una de 64 bits, puede volverse en nuestra contra en algunas situaciones.

El problema es que en estos tiempos de transición entre plataformas muchas de nuestras aplicaciones de .Net que utilizan aun componentes nativos de 32 bits, pueden encontrarse con problemas. Y es que muchos fabricantes de componentes aun están adecuando sus componentes nativos a 64 bits. El problema es que si nuestra aplicación de .Net usa esos componentes de 32 bits nativos y sin embargo se ejecuta sobre una plataforma de 64 bits el ‘casque’ es inevitable ya que no se podrán cargar los componentes de 32 bits en un proces de 64 bits.

Los componentes afectados por esta situación son muchísimos y de muchos fabricantes. Yo he sufrido este problema con proveedores de datos de Microsott para Oracle, con componentes de Active Reports (estos ya han solucionado la papeleta), con librerías de comunicación de dispositivos etc…

Ya hablá de este problema y de como solucionarlo en aplicaciones Asp.net, hoy toca ver que podemos hacer si nuestra aplicación es un ejecutable, sea un servicio, una aplicación de consola o de ventana.s

La solución pasa porque el proveedor del componente lo migre a 64 bits o por ejecutar nuestro proceso de .Net como un proceso de 32 bits aunque la máquina sea de 64 bits. Para ello basta con compilar nuestra aplicación para 32 bits (x86) en lugar de para cualquier CPU (Any CPU). La manera correcta de hacer esto en Visual Studio es crear una nueva plataforma para la solución de tipo x86:

Y luego establecer las propiedades de compilación para esta plataforma adecuadamente en las propiedes de compilación del proyecto:

Esto funciona bien cuando sabemos a priori cual es la situación. Pero lo que a veces ocurre es que descubrimos que una aplicación ya compilada no se comporta como debería en máquinas de 64 bits. Podríamos recompilarla con la configuración comentada arriba, lo que exige tener o podemos parchearla sin recompilarla para forzar su ejecución en 32 bits. Para ello en el framework de .Net tenemos una herramienta llamada corflags que nos pemite marcar cualquier ejecutable de .Net para que se fuerce su ejecución como 32 bits aunque el sistema sea de 64 bits.

Unsando el comando Cordflags MiAplicacion.exe /32BIT+ nuestra aplicación será capaz de utilizar los componentes de 32 bits sin ningún problema en una máquina de 64 bits.

Cómo cazar una fuga de memoria en .Net (y II)

Comentaba hace unos días como he sufrido una fuga de memoria en .Net, esas que en teoria son ‘imposibles’ y presentaba un caso mínimo que lo reproducía. Luego, explique como dilucidar si se trataba de una fuga de memoria manejada o de memoria nativa. Hoy toca hablar de cómo llegue a determinar en que lugar exacto del código se estaba produciendo la fuga de memoria en cuestión.

La herramienta que utlice para ello fue el CLR Profiler, que nos permite monitorizar todas las asignaciones de memoria que realiza una aplicación manejada. Para ello basta con ejecutar la aplicación bajo la supervisión del CLR Profiler. Podeís descargar esta poderosa herramienta de manera totalmente gratuita. Para instalar la aplicación solo es necesario ejecutar el archivo autodescomprimible.

Para ejecutar una aplicación bajo el profiler basta con pulsar sobre el botón Start Application… y seleccionar el ejecutable de nuestra aplicación. Si se trata de un servicio o una aplicación Asp.net tenemos que usar el menu File y elegir Profile Service… o Profile ASP.NET. Es importante ejecutar el profiler con permisos de administrador, sino no será capaz de adjuntarse a la aplicación y recoger datos sobre las asignaciones de memoria realizadas por la aplicación.

image

Una vez ejecutada nuestra aplicación bajo el profiler podemos usar el botón Show Heap now, que aparecerá habilitado, para ver el estado de la memoria de la memoria de nuestro proceso. Esto nos permite obtener una imagen de la memoria en un instante determinado y también comparar los objetos que tenemos en memoria en dos instantes determinados. El profiler nos da numerosas representaciones de las asignaciones de memoria, en concreto me voy a fijar ahora en la representación en forma de histograma. Esta representación nos da una idea visual de que objetos son los más numerosos de los que nuestra aplicación crea, evidentemente si tenemos una fuga de memoria relacionada con memoria manejada tendremos un gran numero de objetos de los que son responsables de la fuga. Aplicando el profiler al caso mínimo que publique en mi primer post y mostrando la vista de histograma (menu contextual Show Histogram) vemos como System.WeakReference es el objeto más numeroso de los creados por nuestra aplicación.

image

Ahora nos queda saber quien esta creando ese objeto. Para ello, con el menu contextual  de la barra del histograma Show who allocated nos permite ver en forma de arbol que funciones son las que han creado esos objetos. Vemos que aquí ya aparecen funciones de nuestro código, lo que sin duda nos llevará a tras inspeccionar el código plantear una hipótesis fundamentada sobre por qué se esta producciendo la fuga.

image

Una vez terminada la ejecución de la aplicación, podemos obtener un motón de información sobre como se comportó la aplicación en lo relativo a la memoria.

image

A la hora de cazar fugas de memoria es especialmente útil la vista de línea de tiempos (botón Time Line)

image

Esta vista nos muestra como nuestra aplicación asigna memoria y la libera (se presenta una típica figura de dientes de sierra) y como hay una porción creciente de memoria que nunca se libera (area roja). Pinchando en ese area, podemos ver que se corresponde con objetos WeakReference. Una vez más podemos usar el menu contextual Show Who Allocated para saber que funciones son las reponsables de la cración de dichos objetos.

Otra información relevante que nos da este gráfico es la cantidad de memoria que tenemos en colecciones de segunda generación (area amarilla) o lo que es lo mismo el volumen de objetos que está sobreviviendo de manera persistente al recolector de factura, comportamiento sintomático de un problema de fuga de memoria. En este caso vemos como el volumen de las colecciones de segunda generación cada vez crece mas y como es debido precisamente a objetos de tipo WeakReference. Igual que antes podemos usar el menu contextual Show Who Allocated para obtener información de que funciones son las responsables de la creación de dichos objetos.

El CLR Profiler es una poderosa herramienta a la hora de diagnosticar problemas de memoria de nuestra aplicación, sean estos fugas de memoria o un consumo demasiado alto de la misma.