Cet petit article fait suite à celui ci où j’expliquais ma façon de gérer le stockage des données dans mon application. Les exemples choisis étaient volontairement simple afin de mieux me concentrer sur l’architecture que je proposais. Aujourd’hui, je vais continuer en proposant un nouveau type de container pour faire persister les objets.
Je travaille actuellement sur un site web hébergé en Web Farm. Il doit y avoir un dizaine de serveur je pense dans ma ferme, et je me heurte par conséquent À un problème, celui des variables d’application.
En effet si je modifie dynamiquement ma variable d’application via un interface web, je ne l’aurais fait en fait que sur un seul serveur pas sur les 9 autres, qui continueront avec leurs propres collection de variable d’application. Pour mettre à jour, le s9 autres , il va falloir que que je rappelle ma site plusieurs fois afin d’avoir la chance de tomber sur tous mes serveurs de ma ferme et ainsi mettre a jour ma valeur. Bref pas très pratique tout ca..
Pour cela j’ai imaginé un nouveau type de container. Rien de bien sorcier en fait, il s’agit juste d’un cache avec une durée d’expiration et qui prend en entrée une fonction. Cette fonction lui indique comme aller chercher les données à mettre à jour.
Ainsi, si je mets a jour une variable d’application, je met a jour en même temps ma base de données, et au bout de x minutes, chaque container ira de lui même , grâce à la fonction, rechercher la valeur qui va bien pour chaque serveur de ma web farm.
Un peu de code pour illustrer mon propos. Voici une classe MonApplication qui contient les données générales propres au contexte de mon appli.
public class MonApplication
{
public DateTime? AppOfflineStartDate { get; set; }
public DateTime? AppOfflineEndDate{ get; set; }
public bool IsAppOffline{ get; set; }
public Robots Robot{ get; set; }public bool GetApplicationOnline()
{
bool returnvalue = this.IsAppOffline;//the dates indicated have priority on the status to put the application offline
if (this.AppOfflineStartDate.HasValue && this.AppOfflineEndDate.HasValue)
{
if (DateTime.Now > this.AppOfflineStartDate.Value && DateTime.Now < this.AppOfflineEndDate)
returnvalue = true;
}
else
{
// either AppOfflineStartDate or AppOfflineEndDate is null, may be both of themif (this.AppOfflineStartDate.HasValue)
{
if (DateTime.Now > this.AppOfflineStartDate.Value)
returnvalue = true;
}if (this.AppOfflineEndDate.HasValue)
{
if (DateTime.Now < this.AppOfflineEndDate)
returnvalue = true;
}if (!this.AppOfflineStartDate.HasValue && !this.AppOfflineEndDate.HasValue)
{
//do nothing the basic IsAppOnline should prevail
}
}return returnvalue;
}}
Rien de Bien compliqué ici. Il s’agit juste de savoir si mon application doit être on line ou non. Et pour cela, on va chercher les informations dans un base de données grâce à ce service.
public class KjuApplicationService
{
public KjuApplication GetKjuApplication()
{KjuApplication kjuappli = new KjuApplication();
//Bloc de code pour aller chercher les données dans la base de données ici
Robots Bob = new Robots();
Bob.Indexed = true;
Bob.LinkTofollows = true;kjuappli.Robot = Bob;
return kjuappli;
}
}
L’appel À notre container va se faire de la sorte :
public static MonApplication monAppli {
get {
StoringContainerProvider container = StoringContainerFactory.GetInstance(StoringContainerFactory.E_StoringContainerType.DynamiqCache);
KjuApplicationService kas =new KjuApplicationService();
return (KjuApplication)((StoringContainerDynamiqCache)container).LoadObject(“KjuAppli”, kas.GetKjuApplication, 5);
}
set {
StoringContainerProvider container = StoringContainerFactory.GetInstance(StoringContainerFactory.E_StoringContainerType.DynamiqCache);
container.SaveObject(value,”KjuAppli”);
}
}
Ce qui change ici est exclusivement la partie get, car avec mon nouveau container “DynamiqCache”, je vais lui donner la fonction du service que j’ai détaillée avant.
public object LoadObject(string ContainerKey, Func<Object> FetchObject, double minutes)
{
//have a look if the cached object is not present
if (HttpContext.Current.Cache.Get(ContainerKey) == null)
{
Object ObjToBeSaved = FetchObject();
this.SaveObject(ObjToBeSaved, ContainerKey, minutes);
}
return HttpContext.Current.Cache[ContainerKey];
}
Et voilà le travail, j’ai maintenant un container générique qui va pouvoir mettre À jour ses données si on lui dit comment faire.
N’hésitez pas à me laisser des commentaires si vous voyez des erreurs ou si si vous trouvez qu’il y a des choses À améliorer.
Salut,
Il me semble que SQL Server peut adresser des requêtes http sur des trigers (insertion, mise à jour d’un champ). Ainsi dès que tu ajoutes ou modifie ta variable, tu peux configurer SQL Server pour envoyer des requêtes http sur chacun de tes serveurs. Ainsi, tes sites sont beaucoup plus réactifs.
http://msdn.microsoft.com/en-us/library/ms140114.aspx
A+
Par Immobilis le 10 mars 2010
à 12:03
Merci Immobilis. Je ne connaissais pas cette fonction de SQL Server, bien pratique ma foi! Cela permettrait de contourner ma solution de façon élégante!
Malheureusement pour moi, Je n’ai aucun accès à ma ferme de serveur et par conséquent je ne peux pas m’adresser distinctement à chaque serveur afin d’y réaliser une opération .
Par yoannr le 10 mars 2010
à 11:21