Я создаю службу WCF. Мне нужно хранить справочные данные в кеше, которые я буду искать каждый раз, когда получаю вход от метода... Каков правильный способ сделать это? Я также хотел бы определить политику истечения срока действия кэша, которая будет лишать ее права после определенного интервала времени.
Кэширование в WCF?
Ответ 1
Если вы используете .NET 4, рекомендуется использовать MemoryCache
Ответ 2
Любое решение кэширования должно касаться двух основных проблем
1) Хранение элементов кэша и поиска
2) Недействительность кэша
Так как кэширование Http является хорошо известным, я не буду подробно объяснять его. Вы можете использовать только атрибут совместимости asp с некоторой веб-конфигурацией, где вы получите кеширование по очарованию.
[AspNetCacheProfile("MyProfile")]
public Customer GetName(string id)
{
// ...
}
И веб-конфиг похож на
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
</system.serviceModel>
<system.web>
<caching>
<outputCacheSettings>
<outputCacheProfiles>
<add name=" MyProfile" duration="600" varyByParam="none" sqlDependency="MyTestDatabase:MyTable"/>
</outputCacheProfiles>
</outputCacheSettings>
</caching>
</system.web>
Но это не подходит для большинства сценариев, особенно когда у вас есть большой сложный объект для кеширования. Например, у меня была ситуация, когда я хотел кэшировать сгенерированное системой изображение (вывод рабочего контракта - это сгенерированное системой изображение, зависящее от ввода). В таком случае вы должны реализовать свой собственный кеш. Я использовал блоки кэширования корпоративной библиотеки Microsoft, которые учитывали все требования к кэшированию хранилища. Тем не менее, вам все равно нужно сделать сантехнику, чтобы интегрировать блок кэширования корпоративной библиотеки Microsoft с помощью службы WCF. Сначала вам нужно перехватить канал связи WCF для реализации кеша. Подробное обсуждение того, как перехватить канал связи WCF, можно найти на http://msdn.microsoft.com/en-us/magazine/cc163302.aspx. Так вы делаете сантехнику для кэширования WCF
Шаг 0 Допустим, у вас есть контракт на операцию следующим образом, и вы хотите кэшировать возвращаемый элемент этим методом.
[OperationContract]
MyCompositeClass Rotate(int angle)
Шаг 1 Сначала вам нужно зарегистрировать свой собственный кэшер в конвейере WCF. Для этого я собираюсь использовать атрибут, чтобы я мог красиво украсить мой вызов WCF в соответствии с принципами ориентации на аспект.
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;
}
/// <summary>
/// Decorate the method call with the cacher
/// </summary>
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;
}
}
Шаг 2
Затем вам нужно реализовать точку, в которой будет извлекаться объект кэша.
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; }
}
}
Шаг 3
Наконец, добавьте свой атрибут над своим служебным вызовом
[OperationContract]
[MyCacheRegister(typeof(RotateCacher)]
MyCompositeClass Rotate(int angle)
Конфигурация блока кэширования корпоративной библиотеки выходит за рамки этого ответа. Вы можете использовать следующую ссылку, чтобы узнать ее. Хорошая вещь в корпоративной библиотеке заключается в том, что вы получаете готовые способы расширения вашей политики кэширования. Он имеет встроенные возможности для истечения срока хранения и хранения кеша. Вы также можете написать свои собственные политики истечения срока хранения и хранения. http://www.codeproject.com/KB/web-cache/CachingApplicationBlock.aspx
Наконец, для того, чтобы вы могли работать с кэшированием своей корпоративной библиотеки, вам нужно добавить следующие данные конфигурации. Вам также необходимо добавить соответствующие DLL-ссылки в ссылку на проект.
<configSections>
<section name="cachingConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Caching.Configuration.CacheManagerSettings, Microsoft.Practices.EnterpriseLibrary.Caching, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="true" />
</configSections>
<cachingConfiguration defaultCacheManager="Cache Manager">
<cacheManagers>
<add name="MemoryCache" type="Microsoft.Practices.EnterpriseLibrary.Caching.CacheManager, Microsoft.Practices.EnterpriseLibrary.Caching, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
expirationPollFrequencyInSeconds="60" maximumElementsInCacheBeforeScavenging="1000"
numberToRemoveWhenScavenging="10" backingStoreName="NullBackingStore" />
<add name="DiskCache" type="Microsoft.Practices.EnterpriseLibrary.Caching.CacheManager, Microsoft.Practices.EnterpriseLibrary.Caching, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
expirationPollFrequencyInSeconds="60" maximumElementsInCacheBeforeScavenging="1000"
numberToRemoveWhenScavenging="10" backingStoreName="IsolatedStorageCacheStore" />
</cacheManagers>
<backingStores>
<add type="Microsoft.Practices.EnterpriseLibrary.Caching.BackingStoreImplementations.NullBackingStore, Microsoft.Practices.EnterpriseLibrary.Caching, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
name="NullBackingStore" />
<add name="IsolatedStorageCacheStore" type="Microsoft.Practices.EnterpriseLibrary.Caching.BackingStoreImplementations.IsolatedStorageBackingStore, Microsoft.Practices.EnterpriseLibrary.Caching, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
encryptionProviderName="" partitionName="MyCachePartition" />
</backingStores>
</cachingConfiguration>
Ответ 3
Вы можете взглянуть на Velocity. Это распределенная в Microsoft
Ответ 4
это хорошая статья: http://cascadeofinsights.com/post/1410736927/introducing-attribute-based-caching
Ответ 5
Если вы собираетесь масштабировать до более чем одного сервера в балансированной нагрузке системе без гражданства, вы захотите дизайн для использования распределенный кеш. Главное здесь:
-
Используйте как локальный, так и распределенный кеш. Только поставить сеанс или короткий в распределенном кеше, в другом кеше вещей.
-
Установите соответствующие тайм-ауты для элементов. Это зависит от тип информации и то, насколько близко к ее источнику.
-
Удалите вещи из кеша, когда вы знаете, что это будет недержанием (например, обновления, удаления и т.д.).
-
Позаботьтесь о создании уникальных кеш-ключей. Построить модель тип информации, которую вы планируете кэшировать, и использовать ее в качестве шаблона для ключи здания.
Ответ 6
Вы можете использовать System.Web.Cache(даже если вы не в веб-контексте), и что я буду делать. Это в основном большая, в хэш-таблице памяти с некоторыми тонкостями для истечения срока содержания.
Ответ 7
Есть много способов сделать это. Один довольно простой способ разместить объект System.Web.Cache самостоятельно и использовать его для хранения справочных данных. Вот хороший пример этого: http://kjellsj.blogspot.com/2007/11/wcf-caching-claims-using.html
Ответ 8
В стартовом наборе WCF REST есть кеширование, вот статья об использовании его... с образцом кода.
Ответ 9
Вместо того, чтобы выгружать данные кэша так часто, вы можете просто удостовериться в том, что вы будете недействительным кэшировать всякий раз, когда изменяются базовые данные, которые вы кэшируете.
См. этот пример из информации 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)
{
...
}