Подтвердить что ты не робот

Кэширование в WCF?

Я создаю службу WCF. Мне нужно хранить справочные данные в кеше, которые я буду искать каждый раз, когда получаю вход от метода... Каков правильный способ сделать это? Я также хотел бы определить политику истечения срока действия кэша, которая будет лишать ее права после определенного интервала времени.

4b9b3361

Ответ 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

Basic Plumbing Architecture

Шаг 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

Ответ 5

Если вы собираетесь масштабировать до более чем одного сервера в балансированной нагрузке системе без гражданства, вы захотите дизайн для использования распределенный кеш. Главное здесь:

  • Используйте как локальный, так и распределенный кеш. Только поставить сеанс или короткий в распределенном кеше, в другом кеше вещей.

  • Установите соответствующие тайм-ауты для элементов. Это зависит от тип информации и то, насколько близко к ее источнику.

  • Удалите вещи из кеша, когда вы знаете, что это будет недержанием (например, обновления, удаления и т.д.).

  • Позаботьтесь о создании уникальных кеш-ключей. Построить модель тип информации, которую вы планируете кэшировать, и использовать ее в качестве шаблона для ключи здания.

Ответ 6

Вы можете использовать System.Web.Cache(даже если вы не в веб-контексте), и что я буду делать. Это в основном большая, в хэш-таблице памяти с некоторыми тонкостями для истечения срока содержания.

Ответ 7

Есть много способов сделать это. Один довольно простой способ разместить объект System.Web.Cache самостоятельно и использовать его для хранения справочных данных. Вот хороший пример этого: http://kjellsj.blogspot.com/2007/11/wcf-caching-claims-using.html

Ответ 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)
{
 ...
}