Caching Application Block

Caching Application Block permite incorporar funcionalidad de caching a una aplicación. Es parte de Enterprise Library 4.1.

Por que usar caching?

Caching mejora el rendimiento de una aplicación manteniendo los datos cerca de donde se usan. Esto evita incurrir, para cada llamada, en los costos de creación, procesamiento y transporte de los datos.
Caching mejorar la escalabilidad de una aplicación porque los servicios que generan los datos son menos exigidos.
Caching puede servir para mejorar la disponibilidad de un aplicación, si se mantiene un cache local esta puede resistir fallas de servicios y latencias de red.

Código de Ejemplo

Primero debe obtener una instancia de un objeto cache, para ello utiliza la fabrica estática CacheFactory. CacheFactory configura el cache con información del archivo de configuración. Puede definir mas de un cache identificandolos por nombre.
Cada cache es una instancia unica (singleton), el método GetCacheManager devuelve siempre la misma instancia. El cache es representado por el tipo ICacheManager.

//Cache sin nombre
ICacheManager cache = CacheFactory.GetCacheManager();

//Cache con nombre
ICacheManager cacheClientes = CacheFactory.GetCacheManager("Clientes");

Para agregar objetos al cache se utiliza el método Add de la clase ICacheManager. En el siguiente ejemplo se agrega un objeto persona al cache:

Persona miPersona = new Persona();
cache.Add("roger", miPersona);

La sobrecarga del metodo add que vimos en el ejemplo anterior asume prioridad Normal y que el objeto nunca expira. Para definir explicitamente la prioridad, políticas de expiración y callbacks se usa una segunda sobrecarga. En el siguiente ejemplo se agrega un objeto Persona al cache definiendo Prioridad Normal, una expiración móvil de 5 minutos y se pasa null para indicar que no se usara callback:

Persona miPersona = new Persona();
productsCache.Add("roger", miPersona, CacheItemPriority.Normal, null, new SlidingTime(TimeSpan.FromMinutes(5)));

Para remover items del cache se utiliza el método Remove:

cache.Remove("roger");

La implementación de Caching Application Block es thread-safe, es decir, se puede utilizar en una aplicación con múltiples hilos de ejecución sin tener que tomar medidas para sincronizar el acceso al cache.

Recolección (Scavenging)

Recolección es el proceso mediante el cual el cache va descartando objetos para evitar ocupar demasiada memoria.
Caching Application Block permite definir un numero umbral de objetos que gatillara el proceso de recolección, y definir el numero de elementos que se recolectaran y eliminaran del cache en cada recolección. Por ejemplo, puede definir el numero máximo de elementos en 1000 y que se descarten 10 elementos cada vez que se ejecute la recolección. Mientras el numero de elementos en el cache sea inferior a 1000 no se ejecutara la recolección, cuando finalmente se llegue a 1000 se ejecutara la recolección y se removerán 10 elementos quedando 990 en el cache. No se volverá a ejecutar la recolección hasta que se vuelva a llegar a 1000 elementos.
El proceso de recolección elije los elementos a remover del cache ordenándolos según dos variables, primero la prioridad asignada al elemento (Low, Normal, High, or Not Removable), y segundo según la ultima hora de acceso al objeto. Es decir, los elementos de menor prioridad y que son menos accedidos serán los primeros em ser eliminados en el proceso de recolección.

Expiración y dependencias

Se pueden definir políticas de expiración que determinan cuando los objetos del cache dejan de ser validos y deben ser removidos.

  • Tiempo absoluto: El objeto deja de ser valido en tal fecha y hora.
  • Tiempo móvil: El objeto deja de ser valido si no es accedido luego de un intervalo de tiempo dado, por ejemplo 5 minutos.
  • Formato de tiempo extendido: Sirve para definir políticas de tiempo complejas como que un objeto deja de ser valido todos los días a las 12 de la noche.
  • Dependencia a archivo: El objeto se liga a un archivo y deja de ser valido cuando ese archivo es modificado.

En el archivo de configuración se puede definir cada cuanto tiempo se lanza el proceso que verifica si hay objetos expirados. El valor por defecto es 60 segundos.

Es posible extender Caching Application Block implementando nuevas políticas de expiración, para ello se debe crear una clase que implemente la interfaz ICacheItemExpiration.

Callback

Es posible configurar que se realice una acción cuando un objeto del cache expire. Esto se logra pasando un objeto que implemente ICacheItemRefreshAction al método Add. La clase que implementa ICacheItemRefreshAction tiene la oportunidad de realizar una acción cuando un objeto expira del cache, por ejemplo podría refrescar los datos y volver a agregarlos.

Configuración

Caching Application Block permite definir uno o mas caches que son identificables por nombre. Cada uno de estos cache se configura en el archivo de configuración. Es posible definir un nombre del cache o dejarlo sin nombre lo cual significa que es el cache por defecto.

Los parametros de configuración son los siguientes:

  • ExpirationPollFrequencyInSeconds: Cada cuanto tiempo se verifica si hay objetos expirados en el cache.
  • MaximumElementsInCacheBeforeScavenging: El numero de elementos que gatilla la recolección.
  • NumberToRemoveWhenScavenging: El numero de elementos a recolectar en cada recolección.

Si va a configurar persistencia del cache, debe definir el lugar de almacenamiento. Si va a usar una base de datos SQL Server como lugar de almacenamiento debe configurar ademas Data Access Application Block pues es usado internamente para ejecutar comandos SQL.

Persistencia

Caching Application Block permite persistir el cache en un medio de almacenamiento, y de esta forma evitar que el cache se pierda cuando la aplicación debe reiniciarse. Se incluyen dos implementaciones de almacenamiento: base de datos Sql Server y Isolated Storage. Es posible extender Caching Application Block implementando nuevos medios de almacenamiento.

Cuando el cache no esta configurado para usar almacenamiento solo se mantiene una copia del cache en memoria que esta disponible mientras este activo el proceso en que se ejecuta la aplicación. Si la aplicación se reinicia el cache se pierde y vuelve a partir vacío.
Cuando se configura un medio de almacenamiento, se mantiene sincronizado el cache en memoria y la copia en el medio de almacenamiento. Cada vez que un objeto es ingresado o es removido del cache en memoria, también se ejecutan los comandos necesarios para ingresarlo o removerlo de la copia de almacenamiento. Cuando la aplicación es reiniciada, Caching Application Block lee la copia del cache desde el lugar de almacenamiento y lo carga en memoria, de esta forma el cache no se inicia vacío.
Este comportamiento del cache solo debe ocuparse en un solo proceso, no es una implementación de cache distribuido que pueda compartirse y sincronizarse entre procesos concurrentes. La extensión NCache, comercializada por una tercera compañía, hace que Caching Application Block se comporte como un cache distribuido.

Caching ASP.NET (System.Web.Caching)

Existe una Implementación de caching en ASP.NET (System.Web.Caching). Es posible usar esta implementación también fuera de ASP.NET en aplicaciones de Consola, Windows Forms y Servicios Windows. Se recomienda usar caching de ASP.NET para la mayoría de los casos y solo preferir Caching Application Block cuando se requiera una característica no disponible en la implementación de ASP.NET.

Las características que podrían inclinar una preferencia a favor de Caching Application Block son:

  • Caching Application Block permite persistencia del cache.
  • Es posible mantener multiples instancias de cache independientes identificables por nombre.
  • Es posibile configurar el cache usando el archivo de configuracion sin necesidad de recompilar la aplicacion.
  • Es extensible, se pueden implementar nuevas politicas de expiracion, medios de almacenamiento, e incluso editar el codigo fuente para incluir nueva funcionalidad.
Vea tambien
Links