Magazine

.NET & cache local / distribué

Publié le 18 mars 2008 par Olivier Duval

.NET 2.0 a introduit la capacité de créer des providers simplement, tout en gérant assez finement la configuration. Ces fournisseurs (ie : 1 fournisseur = 1 implémentation d’une interface / contrat) sont configurables par un fichier .config (XML), et chargeables dynamiquement selon les besoins du client, en y introduisant une abstraction. Un exemple sur le MSDN comme point de départ.

du côté client

On va tenter à partir des providers de créer 2 fournisseurs :

  • un cache local, basé sur le cache d’Asp.Net, ou bien sur le HttpRuntime1 dans le cas d’une assembly non contenue dans une application Web
  • un cache distribué, basé sur Memcached, avec cette API. Il en existe 2 autres, non testées, EnyimMemcached et BeIT Memcached, cette dernière me paraissant très prometteuse.

Ces fournisseurs seront accessibles par un helper (classe statique), celui-ci encapsulant l’implémentation souhaitée (cache distribué ou local).

Le but est d’avoir une utilisation simple de cette classe :

// par défaut le cache local
CacheHelper.Add("cle","ma donnee",60000);
string val= CacheHelper.Get("cle") as string;
// utilisation du cache ditribué
CacheHelper.Strategy = "DistributedCacheProvider";
CacheHelper.Add("sharedkey","ma donnee a partager",60000);
string val2 = CacheHelper.Get("sharedkey") as string;

Je suis parti de ce code auquel j’ai ajouté la notion de stratégie, et de cet excellent article sur les mystères de la configuration .NET.

Chaque fournisseur, que nous appellerons AspNetcachedProvider et MemcachedProvider implémentent la classe abstraite ci-après, qui elle-même hérite de ProviderBase :

public abstract class CacheProvider : ProviderBase
{
public abstract long DefaultExpireTime { get;set;}
public abstract bool Add(string strKey, object objValue);
public abstract bool Add(string strKey, object objValue, bool bDefaultExpire);
public abstract bool Add(string strKey, object objValue, long lNumofMilliSeconds);
public abstract object Get(string strKey);
public abstract object Remove(string strKey);
}

Les providers sont définis dans un fichier de configuration (web.config, app.config ou fichier externe avec l’attribut possible configSource sur la section)

A titre d’exemple, on pourra avoir :



allowDefinition="MachineToApplication" restartOnExternalChanges="true"/>



servers="10.75.92.10:11211" socketConnectTimeout="1000" socketTimeout="1000"/>

Les fournisseurs sont instanciés lors de l’appel de CacheHelper. Cela permet de respecter le principe de Ouvert-Fermé. Ainsi, rien ne nous empêche d’avoir une autre implémentation pour le cache distribué, comme par exemple des données stockées par un serveur de bases de données ou bien une autre implémentation de Memcached (BeITMemcached). Il suffirait alors d’appeler cette implémentation au lieu de Memcached. En conséquence, la configuration se transformerait en :



allowDefinition="MachineToApplication" restartOnExternalChanges="true"/>




Découplé, souple, extensible, j’aime.

Quelques cas d’utilisation

Lorsqu’on utilise les pools d’applications, l’objet Cache n’est pas partagé entre les applications, le cache distribué est là le bienvenu.

Sur une plateforme avec des systèmes hétérogènes (Windows, Linux), partager des données entre plusieurs serveurs peut s’avérer utile, avoir un cache distribué est encore une fois bienvenue.

Enfin, on pourrait penser au besoin de partage d’objets entre une application (fenêtrée, service windows, ...) et une application Web.

Contraintes

Entre le cache local (utilisation de l’objet Cache) et Memcached, le comportement peut-être différent pour le stockage des objets. En effet, Cache permet de stocker n’importe quel objet, contrairement à Memcached qui nécessite que l’objet soit marqué de l’attribut [Serializable], sans quoi la sérialisation échouera.

du côté serveur

serveur memcached 1.2.4 sur Debian

Le package Debian est trop ancien (1.1x), il est préférable de partir des sources : 1.2.4 installée, la 1.2.5 vient de sortir. Il est nécessaire d’avoir libevent (apt-get install libevent-dev).

Suivre ce tutoriel

monitoring

Un plugin est disponible pour Munin afin de monitorer le serveur Memcached, prendre le plugin de 2ème génération.

Cela permet d’avoir des graphes de ce type :

memcached monitoring

memcached monitoring

serveur Windows

Une version Windows est disponible, non testée.

Sources

Le zip Caching.zip contient 3 répertoires :

  • Caching : la librairie pour la gestion des 2 fournisseurs
  • memcacheddotnet : l’implémentation Memcached, API v 1.1.5 trouvée sur Sourceforge
  • Clients, scindé en CachingWebTest et CachingWinTest, 2 applications, Web et Winform qui utilisent le cache – en lançant les 2 en //, vous pourrez accéder à la même donnée partagée

Il suffit d’ouvrir la solution Caching.sln.

1 cela permettra d’utiliser l’objet Cache hors d’une application Web, par exemple dans une assembly, une application console, ...


Retour à La Une de Logo Paperblog

A propos de l’auteur


Olivier Duval 4 partages Voir son profil
Voir son blog

l'auteur n'a pas encore renseigné son compte l'auteur n'a pas encore renseigné son compte