Sunday, March 13, 2011

Caching в WCF сервисе

Кэширование данных неотъемлемая часть высоконагруженных и ресурсоемких проектов. В этой статье я опишу процесс организации оптимального механизма кэширования в WCF сервисе. Сформулирую задачу: имея WCF сервис, нужно организовать кеширование результатов работы любого сервис-метода в зависимости от входных параметров (Caching Support for WCF Services). Существует множество решений поставленной задачи, и самое простое и очевидное, это организовать кэширование прямо в сервис-методе:

public DateTime GetDate()
{
    ICache cache = ...; // получим экземпляр кэша
    string key = "somekey";
    object value;
    // Попробуем достать данные из кэша
    if (!cache.TryGet(key, out value))
    {
        // Данные в кэше отсутствуют,
        // получим новые данные
        value = DateTime.Now;
        // и поместим их в кэш на 5 секунд
        cache.Add(key, value, TimeSpan.FromSeconds(5));
    }
    return (DateTime)value;
}

Из примера видно, что сервис-метод GetDate перегружен логикой кэширования, и с появлением еще одного аналогичного сервис-метода, логика кэширования будет просто скопирована в него. Очевидно, что такой подход приведет к тому, что со временем такой код станет труднее поддерживать при изменении схемы кэширования, и естественно возникает вопрос об организации функционала сквозного кэширования. Организовать такую функциональность можно через AOP или в случае с WCF можно воспользоваться стандартным механизмом перехвата вызова через специальные интерфейсы (WCF Interceptor Interfaces), а точнее через интерфейс IOperationInvoker.

И, предже чем приступить к реализации наметим основные шаги:
  • Для начала создадим простой WCF сервис
  • Объявим интерфейс кэша ICache
  • Реализуем свой перехватчик (IOperationInvoker)
  • И закончим реализацией IOperationBehavior атрибута для нашего перехватчика
Шаг 1. Создадим новый WCF проект, назовем его MyService, с контрактом в виде интерфейса:
[ServiceContract]
public interface IMyService
{
    [OperationContract]
    DateTime GetDate();
}

Read more: HANDCODE