Caching dans WCF?

Je construis un service WCF. J’ai besoin de stocker des données de référence dans le cache que je rechercherai chaque fois que je reçois des données de la méthode … Quelle est la bonne façon de procéder? Je voudrais également définir une politique d’expiration pour le cache qui l’invalidera après un certain intervalle de temps.

Si vous utilisez .NET 4, la méthode recommandée consiste à utiliser MemoryCache

Toute solution de mise en cache devrait résoudre deux problèmes de base

1) Stockage des éléments en cache et récupération

2) invalidation du cache

Comme la mise en cache HTTP est bien connue, je ne vais pas l’expliquer en détail. Vous pouvez utiliser l’atsortingbut de compatibilité ASP uniquement avec une configuration Web, où vous obtiendrez une mise en cache charmante.

[AspNetCacheProfile("MyProfile")] public Customer GetName(ssortingng id) { // ... } 

Et la configuration web est comme

             

Mais cela ne convient pas à la plupart des scénarios, en particulier lorsque vous devez mettre en cache un object complexe volumineux. Par exemple, je souhaitais mettre en cache une image générée par le système (la sortie du contrat d’exploitation est une image générée par le système qui dépend de l’entrée). Dans un tel cas, vous devez implémenter votre propre cache. J’ai utilisé des blocs de mise en cache de bibliothèques d’entreprise Microsoft qui répondaient à toutes mes exigences en matière de stockage en cache. Cependant, vous devez toujours effectuer le plomberie pour intégrer le blocage de la mise en cache de la bibliothèque d’entreprise Microsoft à votre service WCF. Vous devez d’abord intercepter le canal de communication WCF pour implémenter le cache. Une discussion détaillée sur la façon d’intercepter le canal de communication WCF peut être trouvée à http://msdn.microsoft.com/en-us/magazine/cc163302.aspx . Voici comment vous faites la plomberie pour la mise en cache WCF

Architecture de plomberie de base

Etape 0 Disons que vous avez un contrat d’opération comme suit et que vous souhaitez mettre en cache le retour d’article par cette méthode.

 [OperationContract] MyCompositeClass Rotate(int angle) 

Étape 1 Vous devez d’abord enregistrer votre cache personnalisé dans le pipeline WCF. Pour ce faire, je vais utiliser un atsortingbut afin que je puisse décorer joliment mon appel WCF selon les principes de programmation d’orientation.

 using System; using System.ServiceModel.Description; using System.ServiceModel.Channels; using System.ServiceModel.Dispatcher; using System.Reflection; [AtsortingbuteUsage(AtsortingbuteTargets.Method)] public class MyCacheRegister : Atsortingbute, IOperationBehavior { ConstructorInfo _chacherImplementation; public ImageCache(Type provider) { if (provider == null) { throw new ArgumentNullException("Provider can't be null"); } else if (provider.IsAssignableFrom(typeof(IOperationInvoker))) { throw new ArgumentException("The type " + provider.AssemblyQualifiedName + " does not implements the interface " + typeof(IOperationInvoker).AssemblyQualifiedName); } else { try { Type[] constructorSignatureTypes = new Type[1]; constructorSignatureTypes[0] = typeof(IOperationInvoker); _chacherImplementation = provider.GetConstructor(constructorSignatureTypes); } catch { throw new ArgumentException("There is no constructor in " + provider.AssemblyQualifiedName + " that accept " + typeof(IOperationInvoker).AssemblyQualifiedName + " as a parameter"); } } } public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters) { return; } public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation) { return; } ///  /// Decorate the method call with the cacher ///  public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation) { //decorator pattern, decorate with a cacher object[] constructorParam = new object[1]; constructorParam[0] = dispatchOperation.Invoker; dispatchOperation.Invoker = (IOperationInvoker)_chacherImplementation.Invoke(constructorParam); } public void Validate(OperationDescription operationDescription) { return; } } 

Étape 2

Ensuite, vous devez implémenter le point où l’object cache sera récupéré.

 using System; using System.ServiceModel.Dispatcher; using Microsoft.Practices.EnterpriseLibrary.Caching; using Microsoft.Practices.EnterpriseLibrary.Common; using System.IO; class RotateCacher : IOperationInvoker { private IOperationInvoker _innerOperationInvoker; public RotateImageCacher(IOperationInvoker innerInvoker) { _innerOperationInvoker = innerInvoker; } public object[] AllocateInputs() { Object[] result = _innerOperationInvoker.AllocateInputs(); return result; } public object Invoke(object instance, object[] inputs, out object[] outputs) { object result=null; ///TODO: You will have more object in the input if you have more ///parameters in your method ssortingng angle = inputs[1].ToSsortingng(); ///TODO: create a unique key from the inputs ssortingng key = angle; ssortingng provider = System.Configuration.ConfigurationManager.AppSettings["CacheProviderName"]; ///Important Provider will be DiskCache or MemoryCache for the moment provider =”DiskCache”; ///TODO: call enterprise library cache manager, You can have your own /// custom cache like Hashtable ICacheManager manager = CacheFactory.GetCacheManager(provider); if (manager.Contains(key)) { result =(MyCompositeClass) manager[key]; } else { result =(MyCompositeClass) _innerOperationInvoker.Invoke(instance, inputs, out outputs); manager.Add(key, result); } return result; } public IAsyncResult InvokeBegin(object instance, object[] inputs, AsyncCallback callback, object state) { IAsyncResult result = _innerOperationInvoker.InvokeBegin(instance, inputs, callback, state); return result; } public object InvokeEnd(object instance, out object[] outputs, IAsyncResult asyncResult) { object result = _innerOperationInvoker.InvokeEnd(instance, out outputs, asyncResult); return result; } public bool IsSynchronous { get { return _innerOperationInvoker.IsSynchronous; } } } 

Étape 3

Ajoutez enfin votre atsortingbut au-dessus de votre appel de service

 [OperationContract] [MyCacheRegister(typeof(RotateCacher)] MyCompositeClass Rotate(int angle) 

La configuration du bloc de mise en cache de la bibliothèque d’entreprise dépasse le cadre de cette réponse. Vous pouvez utiliser le lien suivant pour l’apprendre. La bonne chose à propos de la bibliothèque d’entreprise est que vous obtenez des moyens prêts à étendre votre politique de mise en cache. Il a intégré des moyens d’expiration et de stockage du cache. Vous pouvez également écrire vos propres stratégies d’expiration et de stockage du cache. http://www.codeproject.com/KB/web-cache/CachingApplicationBlock.aspx

Une dernière chose: pour que la mise en cache de votre bibliothèque d’entreprise fonctionne, vous devez append les détails de configuration suivants. Vous devez également append des DLL pertinentes à votre référence de projet.

  

Vous pouvez regarder Velocity . Il s’agit de la structure de cache en mémoire dissortingbuée de Microsoft. Mais cela peut être un peu trop bêta …

Si vous voulez évoluer vers plusieurs serveurs dans un système sans charge et équilibré, vous devez concevoir un cache dissortingbué . Les principales choses à faire ici sont:

  1. Utilisez à la fois un cache local et un cache dissortingbué. Ne placez que des données de session ou de courte durée dans le cache dissortingbué, d’autres cache de matériel localement.

  2. Définissez les délais d’attente appropriés pour les éléments. Cela varie en fonction du type d’informations et de la proximité de la source.

  3. Supprimez les éléments du cache lorsque vous savez qu’il sera incontinent (comme les mises à jour, les suppressions, etc.).

  4. Veillez à concevoir des clés de cache uniques. Créez un modèle du type d’informations que vous prévoyez de mettre en cache et utilisez-le comme modèle pour créer des clés.

Vous pouvez utiliser System.Web.Cache (même si vous n’êtes pas dans un contexte Web), et c’est ce que je ferais. C’est en gros une grande table de hachage en mémoire avec quelques détails pour expirer les contenus.

Il y a plusieurs façons de le faire. Il est assez facile d’héberger vous-même l’object System.Web.Cache et de l’utiliser pour stocker les données de référence. Il y a un bon exemple de cela ici: http://kjellsj.blogspot.com/2007/11/wcf-caching-claims-using.html

Le Kit de démarrage REST WCF a la mise en cache, voici un article sur son utilisation … avec un exemple de code.

http://weblogs.asp.net/gsusx/archive/2008/10/29/adding-caching-to-wcf-restful-services-using-the-rest-starter-kit.aspx

Plutôt que d’expirer les données de cache de temps en temps, vous pouvez simplement vous assurer d’invalider le cache chaque fois que les données sous-jacentes que vous mettez en cache changent.

Voir cet exemple à partir de l’info Q http://www.infoq.com/news/2011/04/Atsortingbute-Caching

 [Cache.Cacheable("UserTransactionCache")] public DataTable GetAllTransactionsForUser(int userId) { return new DataProvider().GetAllTransactionsForUser(userId); } [Cache.TriggerInvalidation("UserTransactionCache")] public void DeleteAllTransactionsForUser(int userId) { ... }