Memorizzazione nella cache nella WCF?

Sto costruendo un servizio WCF. Ho bisogno di memorizzare i dati di riferimento nella cache che cercherò ogni volta che riceverò input dal metodo … Qual è il modo giusto per farlo? Vorrei anche definire una politica di scadenza per la cache che la invaliderà dopo un certo intervallo di tempo.

Se si utilizza .NET 4, il modo consigliato è utilizzare MemoryCache

Qualsiasi soluzione di caching dovrebbe risolvere due problemi di base

1) Archiviazione degli elementi della cache e recupero

2) Invalidità della cache

Dal momento che il caching Http è ben noto, non lo spiegherò nei dettagli. È ansible utilizzare l’attributo di compatibilità asp da solo con alcune configurazioni Web, dove si otterrà il caching in base al fascino.

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

E la configurazione web è come

             

Ma questo non è adatto alla maggior parte degli scenari, specialmente quando si ha un big oggetto complesso da memorizzare nella cache. Ad esempio, ho avuto una situazione in cui volevo memorizzare nella cache un’immagine generata dal sistema (l’output del contratto operativo è un’immagine generata dal sistema che dipende dall’input). In tal caso, devi implementare la tua cache. Ho utilizzato i blocchi di memorizzazione nella cache della libreria aziendale Microsoft che hanno risolto tutti i requisiti di archiviazione nella cache. Tuttavia, è ancora necessario eseguire l’impianto idraulico per integrare il blocco di memorizzazione nella cache della libreria aziendale Microsoft con il servizio WCF. Per prima cosa devi intercettare il canale di comunicazione WCF per implementare la cache. Una discussione dettagliata su come intercettare il canale di comunicazione WCF è disponibile all’indirizzo http://msdn.microsoft.com/en-us/magazine/cc163302.aspx . Ecco come si fa l’impianto idraulico per la memorizzazione nella cache di WCF

Architettura idraulica di base

Passaggio 0 Supponiamo di avere un contratto operativo come segue e di voler memorizzare nella cache il ritorno dell’object tramite quel metodo.

 [OperationContract] MyCompositeClass Rotate(int angle) 

Passo 1 Per prima cosa devi registrare il tuo cacher personalizzato nella pipeline WCF. Per farlo userò un attributo in modo che possa decorare in modo piacevole la mia chiamata alla WCF secondo i principi di programmazione dell’aspetto.

 using System; using System.ServiceModel.Description; using System.ServiceModel.Channels; using System.ServiceModel.Dispatcher; using System.Reflection; [AttributeUsage(AttributeTargets.Method)] public class MyCacheRegister : Attribute, 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; } } 

Passo 2

Quindi è necessario implementare il punto in cui verrà recuperato l’object cache.

 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 string angle = inputs[1].ToString(); ///TODO: create a unique key from the inputs string key = angle; string 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; } } } 

Passaggio 3

Infine aggiungi il tuo attributo sopra la tua chiamata di servizio

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

La configurazione del blocco di memorizzazione nella cache della libreria aziendale esula dallo scopo di questa risposta. Puoi utilizzare il seguente link per apprenderlo. La cosa buona della libreria aziendale è che ti sei preparato per estendere la tua politica di caching. Ha integrato modalità per la scadenza e l’archiviazione della cache. È inoltre ansible scrivere la propria scadenza di cache e le politiche di archiviazione. http://www.codeproject.com/KB/web-cache/CachingApplicationBlock.aspx

Un’ultima cosa, per far funzionare la memorizzazione nella cache della tua biblioteca aziendale è necessario aggiungere i seguenti dettagli di configurazione. È inoltre necessario aggiungere DLL rilevanti al riferimento del progetto.

  

Puoi dare un’occhiata a Velocity . Questo è il framework di caching in-memory distribuito da Microsoft. Ma potrebbe essere un po ‘troppo beta …

Se si sta eseguendo il ridimensionamento su più di un server in un sistema con stato di bilanciamento del carico, si dovrà progettare l’uso di una cache distribuita . Le cose principali da fare qui sono:

  1. Utilizza sia una cache locale che distribuita. Metti solo sessioni o cose di breve durata nella cache distribuita, altra roba nella cache locale.

  2. Imposta i timeout appropriati per gli articoli. Questo può variare in base al tipo di informazione e alla vicinanza alla fonte che deve essere.

  3. Rimuovi elementi dalla cache quando sai che sarà incontinente (come aggiornamenti, eliminazioni, ecc.).

  4. Abbi cura di progettare le chiavi della cache che sono uniche. Costruire un modello del tipo di informazioni che si prevede di memorizzare nella cache e utilizzarlo come modello per la creazione di chiavi.

Puoi usare System.Web.Cache (anche se non sei in un contesto web), ed è quello che farei. È fondamentalmente una grande tabella di hash della memoria con alcune sottigliezze per i contenuti in scadenza.

Ci sono molti modi in cui puoi farlo. È abbastanza semplice ospitare l’object System.Web.Cache e utilizzarlo per memorizzare i dati di riferimento. C’è un buon esempio di questo qui: http://kjellsj.blogspot.com/2007/11/wcf-caching-claims-using.html

Lo Starter Kit WCF REST ha il caching, ecco un articolo sull’utilizzo … con codice di esempio.

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

Anziché esaurire i dati della cache ogni tanto, è sufficiente accertarsi di invalidare la cache ogni volta che cambiano i dati sottostanti che si stanno memorizzando nella cache.

Vedi questo esempio da informazioni Q http://www.infoq.com/news/2011/04/Attribute-Caching

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