Блог Белоцерковского Александра

Windows Azure Building Blocks. Сервис Caching.

Advertisements

Несмотря на то, что сервис кэширования является не менее интересным, нежели его “коллеги по цеху” (Access Control Service, Service Bus), написано о нём мало. Этой статьёй открывается цикл, посвящённый практическому использованию Windows Azure Building Blocks. Первая статья – о сервиса Caching.

Сервис Caching позволяет реализовать кэширование на уровне хранения в памяти. Кэшируя частоиспользуемую информацию в памяти, мы можем увеличить производительность системы, так как информация при каждом запросе не считывается с диска, а считывается из гораздо более быстрой памяти. Разумеется, не вся частоиспользуемая информация должна храниться в кэше – лучшим кандидатом для кэширования будет информация, частоиспользуемая и редкоизменяемая. Типичными сценариями использования сервиса являются сохранение состояния сессии и кэширования вывода для ASP.NET. При этом информация хранится в памяти множества серверов. Конкретно для платформы Windows Azure сервис может быть выгоден также сокращением расходов на количество транзакций-обращений к базе данных.

Сервис Caching характеризуется:

К функциональности сервиса относятся (список неполон):

Так называемую пирамиду задержек можно увидеть на рис.1.

Рис. 1. Пирамида задержек.

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

Название хранилища Время доступа
Регистры 1-2нс
Кэш 1 уровня (8-64кб) 3-10нс
Кэш 2 уровня (64кб-2мб) 25-50нс
Общая память 30-90нс
Диск 5-20мс
Оптический диск 100мс-5сек
Магнитная лента 10сек-3мин

Естественно, что, чем ниже время доступа, тем “дороже” это хранилище. Однако большая часть из этого списка недоступна, но разработчик может всегда использовать общую память или диск. Время доступа у них различается достаточно серьезно, поэтому вопроса о том, кэшировать или не кэшировать, стоять не должно.

 

Начало работы

Для начала работы с сервисом кэширования Windows Azure необходимо выполнить соответствующие действия по его настройке на портале управления:

1) Перейдите на вкладку Service Bus, Access Control & Caching (рис. 2).

Рис. 2. Вкладка Service Bus, Access Control & Caching.

2) Выберите Caching в списке сервисов.

3) Нажмите кнопку New в верхнем меню, чтобы открылся диалог создания нового пространства имен для сервиса кэширования (рис. 3).

Рис. 3.

4) Введите название пространства имен, выберите страну-регион (учитывайте ближайшее к вашему сервису расположение!) и размер кэша. Четко планируйте размер кэша и не выбирайте больше чем надо, иначе можно заплатить выше планируемого, и существенно выше (подробнее – https://www.windowsazure.com/en-us/pricing/calculator/advanced/) (рис. 4). Нажмите Create Namespace.

Рис. 4. Настройка пространства имен для сервиса кэширования.

Теперь, выбрав созданное пространство имён, верхняя функциональная панель перестанет быть серой (рис. 5).

Рис. 5.

В этой панели доступна основная функциональность по работе с пространством имен сервиса кэширования. Нажмите на Change Cache Size, чтобы получить диалоговое окно с возможностью увеличить или уменьшить размер кэша (рис. 6).

Рис. 6. Диалоговое окно управления размером кэша.

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

Нажав на кнопку View Client Configuration, вы можете получить код, который необходимо вставить в app.config или web.config вашего приложения для начала использования этого пространства имен (рис. 7).

Рис. 7. Конфигурация пространства имен сервиса кэширования.

Ваше пространство имен автоматически защищается сервисом Access Control Service и вам выдается токен, который и используется для аутентификации ваших запросов в системе.

Использование в приложении

При создании (или после создания) проекта (в нашем случае это ASP.NET MVC 3 проект) вы можете пойти двумя путями – либо работать с конфигурацией вручную, либо установить с помощью NuGet специальный плагин для Windows Azure Caching. Разумеется, гораздо удобнее второй способ, и именно им мы и воспользуемся.

Для установки:

1) Открыв решение, перейдите в соответствующую вкладку – Tools->Library Package Manager и нажмите Manage NuGet Packages for Solution (рис. 8).

Рис. 8. Открытие NuGet-менеджера для решения.

2) Введите в строку поиска windowsazure.caching (рис. 9) и нажмите Install.

Рис. 9. Найденный проект Windows Azure Caching.

Что произойдёт после установки плагина? Ничего особенного – за вас сделают всю работу по прописыванию boilerplate code везде, где необходимо. Давайте посмотрим, что же произошло (и где) после установки плагина.

Первое, и самое главное, изменение – добавление конфигурационного кода в web.config (того самого, который доступен по кнопку View Client Configuration).

 

<dataCacheClients>
    <dataCacheClient name="default">
      <hosts>
        <host name="[Insert Cache EndPoint]" cachePort="22233" />
      </hosts>
      <securityProperties mode="Message">
        <messageSecurity authorizationInfo="[Encrypted ACS token goes here]"></messageSecurity>
      </securityProperties>
    </dataCacheClient>
    <dataCacheClient name="SslEndpoint">
      <hosts>
        <host name="[Insert Cache EndPoint]" cachePort="22243" />
      </hosts>
      <securityProperties mode="Message" sslEnabled="true">
        <messageSecurity authorizationInfo="[Encrypted ACS token goes here]"></messageSecurity>
      </securityProperties>
    </dataCacheClient>
  </dataCacheClients>

Данные для “болванок” в квадратных скобках берутся из панели Properties при выборе пространства имен на портале управления Windows Azure.

Также в web.config добавляются настройки кэширования для сохранения состояния сессии и кэширования вывода. Они стандартны и изменять в них ничего не требуется. Если не надо сохранять состояние сессии и кэшировать вывод – можно закомментировать эти куски кода или вообще удалить.

<sessionState mode="Custom" customProvider="AppFabricCacheSessionStoreProvider">
      <providers>
        <add name="AppFabricCacheSessionStoreProvider" type="Microsoft.Web.DistributedCache.DistributedCacheSessionStateStoreProvider, Microsoft.Web.DistributedCache" cacheName="default" useBlobMode="true" dataCacheClientName="SslEndpoint" />
      </providers>
    </sessionState>
    <caching>
      <outputCache defaultProvider="DistributedCache">
        <providers>
          <add name="DistributedCache" type="Microsoft.Web.DistributedCache.DistributedCacheOutputCacheProvider, Microsoft.Web.DistributedCache" cacheName="default" dataCacheClientName="default" />
        </providers>
      </outputCache>
    </caching>

Перейдём к программированию. Конкретно это приложение будет просто забирать блоб сначала из хранилища, потом из кэша. Представим, что в хранилище блобов у нас уже есть один контейнер и один блоб размером 25 мб (рис. 10). На скриншоте изображен Azure Storage Explorer, удобнейшее средство для управления аккаунтом хранилища. Его можно скачать по ссылке http://azurestorageexplorer.codeplex.com/ .

Рис. 10. Содержимое контейнера.

Подставьте соответствующие значения в болванки в web.config – собственно, там необходимо вставить только наименование пространства имен и токен для Access Control Service. Всё это находится в панели Properties для выбранного пространства имен (рис. 11).

Рис. 11. Панель Properties для выбранного пространства имён.

Добавьте соответствующие библиотеки в ваш проект. Библиотеки находятся в папке Windows Azure SDK (рис. 12).

Рис. 12. Расположение библиотек для сервиса кэширования.

В моем проекте создано два дополнительных класса – CachingLayer.cs и BlobExample.cs (рис. 13). Ниже приведен код обоих классов, а также класса HomeController.cs и представления Index для действия Index контроллера Home с комментариями.

Рис 13. Структура проекта ASP.NET MVC3, привязанного к проекту Windows Azure.

Код класса CachingLayer, реализующего создание одного объекта DataCacheFactory, синглтона, так как создание этого объекта – достаточно тяжелое и дорогостоящая операция для того, чтобы выполнять его при каждой необходимости использовать кэш.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Microsoft.ApplicationServer.Caching;

namespace MvcWebRole1.CachingLogic
{

        public static class CachingLayer
        {
            private static readonly DataCacheFactory factory = new DataCacheFactory(new DataCacheFactoryConfiguration("default"));

            public static DataCache GetCache()
            {
                return factory.GetDefaultCache();
            }

        }
    }

Итак, сначала импортируется необходимое пространство имён Microsoft.ApplicationServer.Caching. Далее в статическом классе CachingLayer создаётся синглтон-объект factory и определяется метод GetCache(), возвращающий объект типа DataCache. При этом мы используем метод GetDefaultCache, то есть возвращаем кэш по умолчанию, определенный в администраторской панели на портале управления. Windows Server AppFabric позволяет иметь несколько именованных кэшей, однако его брат на платформе Windows Azure – Только один. Что касается создания объекта factory – в конструктор DataCacheFactory передается имя конфигурации для использования. При этом, если использовать конструктор без параметра, он опять же загрузит конфигурацию по умолчанию. Если же необходимо загрузить конфигурацию с другим именем, нужно явно указать это имя в параметре.

Код класса BlobExample.cs, реализующего одну операцию – получение блоба – в двух вариантах, из хранилища блобов и из кэша.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Microsoft.ApplicationServer.Caching;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.StorageClient;

namespace MvcWebRole1.CachingLogic
{
    public static class BlobExample
    {
        private static readonly CloudStorageAccount storageAccount =
            CloudStorageAccount.Parse(
                "DefaultEndpointsProtocol=https;AccountName=[];AccountKey=[]);
        public static byte[] getBlob()
        {
            CloudBlobClient cloudBlobClient = new CloudBlobClient(storageAccount.BlobEndpoint, storageAccount.Credentials);
            CloudBlobContainer cloudBlobContainer = cloudBlobClient.GetContainerReference("mycontainer");
            return cloudBlobContainer.GetBlobReference("text.txt").DownloadByteArray();
        }

        public static byte[] getBlobFromCache()
        {
            var data = CachingLayer.GetCache().Get("text.txt");
            if (data == null)
            {
                byte[] blob = getBlob();
                CachingLayer.GetCache().Put("text.txt", blob, TimeSpan.FromMinutes(10));

            }
            return (byte[])data;

        }
    }
}

В данном классе два метода и немного конфигурации. По конфигурации все прозрачно и понятно – согласно разложенному аргументу метода Parse() создается экземпляр типа CloudStorageAccount. В методе getBlob() создаётся облачный клиент блоба, который и содержит основную функциональность по управлению контейнерами и блобами, затем создаётся контейнер (либо получается ссылка на него), после чего получается ссылка на блоб text.txt и сам блоб скачивается в виде массива байт (один из методов скачивания блобов). Во втором методе getBlobFromCache(), сначала из кэша получается объект, затем проверяется, есть ли в кэше данный объект и, если нет, кладётся туда с указанием имени, собственно, контента блоба и временем, на которое будет закэширован данный объект (не более 48 часов – ограничение, накладываемое реализацией Caching для Windows Azure).

Объект DataCache содержит в себе следующие методы:

1. Get: Получение объекта из кэша с указанным именем (ключом).

2. Add: Добавление объекта с указанным ключом в кэш. Данного объекта с данным ключом не должно существовать, иначе будет выброшено исключение.

3. Put: Добавление объекта с указанным ключом в кэш либо замена уже существующего объекта с этим ключом.

4. Remove: Удаление объекта с указанным ключом из кэша.

5. GetCacheItem: Получение объекта из кэша вместе с метаданными и версией этого объекта в виде экземпляра типа DataCacheItem.

 

Код контроллера HomeController, где происходит вызов созданных ранее методов.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Microsoft.WindowsAzure.StorageClient;

namespace MvcWebRole1.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            Stopwatch stopWatch = Stopwatch.StartNew();
            byte[] blobFromBlobStorage =
            CachingLogic.BlobExample.getBlob();
            stopWatch.Stop();
            ViewData["blobStorageCount"] = stopWatch.ElapsedMilliseconds;

            stopWatch = Stopwatch.StartNew();
            byte[] blobFromCachingService =
            CachingLogic.BlobExample.getBlobFromCache();
            stopWatch.Stop();
            ViewData["blobCacheCount"] = stopWatch.ElapsedMilliseconds;
            return View();
        }

        public ActionResult About()
        {
            return View();
        }
    }
}

В методе Index, к которому привязано представление Index, происходит создание объекта таймера, с помощью которого замеряется время выполнения вызывающихся далее методов. В процессе в коллекцию ViewData кладутся значения таймера, которые и выводятся на представлении, код которого приведен ниже.

@{
    ViewBag.Title = "Home Page";
}

Прошло времени в процессе получения блоба из хранилища: @ViewData["blobStorageCount"]
Прошло времени в процессе получения блоба из кэша: @ViewData["blobCacheCount"]

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

Результаты, полученные при развертывании приложения в Windows Azure, весьма показательны. Напоминаю, что размер блоба – 25 мб. (рис.14).

Рис. 14. Результаты выполнения приложения.

Advertisements

Advertisements