Как спроектировать кеш веб-сервиса в c # - PullRequest
4 голосов
/ 26 ноября 2010

Я работаю над веб-сервисом, чтобы прочитать данные из стороннего канала, немного изменить их и сохранить, а затем вернуть их своим клиентам.Это нужно только периодически обновлять со стороннего сайта.Он будет работать как служба WCF в веб-роли в Azure.

Сначала я подумал, что просто всегда буду вызывать мой метод parsefeed, но возвращаю этот вызов, если последнее обновление было слишком рано...

   public void ParseFeed()
    {
        if (DateTime.Now > lastrun.AddMinutes(1))
        {
         //Fetch updated data into something shared here.
         //thedata is a public static in Global class 
         thedata = fetchdata();
         lastrun=DateTime.Now;            
        }
    }

Но я полагаю, что при получении может потребоваться 1-2 секунды (это веб-служба), что несколько пользователей одновременно получат этот код.

из http://support.microsoft.com/default.aspx?scid=kb;en-us;Q312607 Поскольку статические члены любого класса, включая класс приложения, не являются поточно-ориентированными, код пользователя должен обеспечивать соответствующую блокировку для доступа к статическим членам.Это относится к любому статическому члену, который вы добавляете в класс приложения.

  • Я мог бы использовать блокировку (не знаю, как) РЕДАКТИРОВАТЬ: много информации здесь

  • Я мог бы избежать статической переменной var и использовать кеш и помещать в него свои данные (но это было бы удалено по истечении срока, и несколько пользователей попытались бы извлечь данные)

  • Я мог бы использовать кэш с поддельным элементом данных в нем (в основном как таймер) и обновлять его по истечении этого срока - но это обновило бы, даже если никто не заходил на сайт.(Может также не быть потокобезопасным)

  • Я действительно не могу использовать выходной кэш, потому что клиенты запрашивают данные, которые я возвращаю, таким образом, что, вероятно, делает каждый запрос уникальным: сортировка моей службыи фильтры в соответствии с запросом

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

У меня такое ощущение, что есть простое решение, которое я полностью пропустил.Идеи?

Ответы [ 2 ]

1 голос
/ 26 ноября 2010

По вашему вопросу это выглядит следующим образом:

  • Недопустимо обслуживать данные, которые устарели более чем на минуту
  • Допустимо, если два экземпляра службы возвращают разныеданные из-за несинхронизации времени обновления
  • Для вызывающих абонентов допустимо блокировать их на 1-2 секунды при обновлении данных

При условии, что все они верны, самое простое решениепросто использовать статическую переменную для хранения данных с конструкцией lock вокруг всего блока проверки / обновления.Я бы даже не стал пытаться делать что-то умное, например, шаблон двойной проверки;Конфликт блокировок просто не будет проблемой, так как время, проведенное в критической области, станет незначительным по сравнению с издержками, связанными с работой веб-службы, за исключением случаев, когда он блокируется и все равно должны блокироваться.

1 голос
/ 26 ноября 2010

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

...