Поделиться через


Основы хранилища Windows Azure. Блобы. (ru-RU)

Компонент хранилища “облачной” платформы Windows Azure предоставляет масштабируемое хранилище. Компонент хранилища не имеет возможности использовать реляционную модель и является альтернативой (либо дополняющим решением) SQL Azure – масштабируемой “облачной” версией SQL Server.

В хранилище Windows Azure существует четыре абстракции, отвечающих за сервисы хранилища:

1) Блобы – простые именованные файлы + метаданные

2) Диски– долговечные тома NTFS, используемые приложениями Windows Azure. Основаны на блобах

3)Таблицы– структурированное хранилище. Таблица – множество сущностей, сущность – множество свойств

4)Очереди – надежное хранение и доставка сообщений для приложения

http://hpcru.files.wordpress.com/2012/03/image_thumb34.png?w=427&h=321

Блобы

На изображении представлена концептуальная архитектура и адресация ссылок на блобы.

http://hpcru.files.wordpress.com/2012/03/image_thumb35.png?w=432&h=325

  • Аккаунт– весь доступ к хранилище происходит через аккаунт хранилища, и имя аккаунта является первым сегментом в ссылке на блоб.
  • Контейнер блобов:
    • Аналогично папке верхнего уровня
    • Может содержать до 100Тб файлов
    • Может содержать только блобы
    • Каждый контейнер имеет права доступа:

-Приватные

-По умолчанию, для доступа нужен ключ аккаунта

-Полное публичное чтение

-Публичное только чтение

    • Контейнер содержит множество блобов
    • Много контейнеров на аккаунт
    • Специальный корневой контейнер $root
    • Можно определить права доступа на уровне контейнера
    • Можно привязать к контейнеру метаданные
    • Нет поисковых запросов типа WHERE MetadataValue = ?
  • Блоб – Блобы могут иметь ассоциированные с ними метаданные в виде пар ключ-значение и размером до 8 килобайт на блоб.

Существует два типа блобов:

  • Блочный блоб– для потоковых нагрузок.
    • Каждый блоб – последовательность блоков.
    • Каждый блок определяется Block ID. Размер ограничен 200Гб на блоб
    • Оптимистичный параллелизм через ETags. Модификация блоба – двухэтапный процесс. Сначала блоки загружаются в хранилище как неподтвержденные блоки для конкретного блоба, после чего для создания обновленного блоба используется метод PutBlockList.

http://hpcru.files.wordpress.com/2012/03/image_thumb36.png?w=426&h=320

  • Страничный блоб – для операций случайного чтения и записи.
    • Каждый блоб – массив страниц.
    • Каждая страница определяется отступом от начала блоба. Размер ограничен 1Тб на блоб
    • Оптимистичный или пессимистичный (блокировка) параллелизм через Leases. Обновление происходит сразу же по завершению запроса на запись последовательного набора страница, поэтому блоки не надо подтверждать (commit).

http://hpcru.files.wordpress.com/2012/03/image_thumb37.png?w=427&h=321

Необходимо учитывать различия, имеющиеся между хранилищем блобов в локальном эмуляторе и хранилищем блобов в облаке.

Операции, доступные для управления блобами в хранилище Windows Azure:

Синхронное создание контейнера блобов:

        public static void CreateBlobContainer(string container)
        {

//получение настройки конфигурации хранилища
            var blobClient = CloudStorageAccount.FromConfigurationSetting("DataStorage").CreateCloudBlobClient();

//создание ссылки на контейнер
            var blobContainer = blobClient.GetContainerReference(container);

//создание контейнера
            blobContainer.CreateIfNotExist();
        }

Сначала создается blobClient типа CloudBlobClient, необходимый для предоставления операций, доступных для управления блобами и контейнерами блобов, после чего получается ссылка на контейнер блобов и с помощью метода CreateIfNotExists контейнер создается, если его ранее не было. Доступен также метод Create, однако в случае существования контейнера с таким именем будет выброшено исключение, поэтому безопаснее использовать CreateIfNotExists.

При создании контейнера блобов необходимо учитывать следующие ограничения:

- Имя контейнера должно начинаться с буквы или цифры, и может содержать только буквы, цифры и символы дефиса.

- Все буквы должны быть низшего регистра.

- Длина имени должна быть от 3 до 63 символов.

- Имя не может содержат дефис после точки.

Таким образом, у вас не получится создать контейнер с именем myContainer – только mycontainer.

Асинхронное создание контейнера блобов:

        public static void CreateBlobContainerAsync(string container)
        {

//получение настройки конфигурации хранилища
            var blobClient = CloudStorageAccount.FromConfigurationSetting("DataStorage").CreateCloudBlobClient();

//получение ссылки на контейнер
            var blobContainer = blobClient.GetContainerReference(container);

//начало процесса создания контейнера
            blobContainer.BeginCreateIfNotExist(EndCreateCloudBlobContainer, blobContainer);
        }
        public static void EndCreateCloudBlobContainer(IAsyncResult asyncResult)
        {
            var blobContainer = (CloudBlobContainer)asyncResult.AsyncState;
            blobContainer.EndCreateIfNotExist(asyncResult);
        }

Удаление контейнера блобов:

       protected void DeleteBlobContainer(string containerName)
        {
//получение настройки конфигурации хранилища            

CloudBlobClient blobClient = CloudStorageAccount.FromConfigurationSetting("DataStorage").CreateCloudBlobClient();

//получение ссылки на контейнер
            var blobContainer = blobClient.GetContainerReference(containerName);

//удаление контейнера
            blobContainer.Delete();

        }

Создание блоба

Для создания блоба в указанном контейнере достаточно воспользоваться методом GetBlobReference объекта контейнера, передав ему наименование блоба. После этого будет создан пустой блоб, который необходимо чем-либо заполнить.

        protected void AddBlob()
        {
            try{

//получение настройки конфигурации хранилища
            CloudBlobClient blobClient = CloudStorageAccount.FromConfigurationSetting("DataStorage").CreateCloudBlobClient();

//получение ссылки на контейнер mycontainer
            var blobContainer = blobClient.GetContainerReference("mycontainer");

//получение ссылки на блоб newblob
            var blob = blobContainer.GetBlobReference("newblob");

//загрузка в блоб файла Untitled.wmv
            blob.UploadFile(@"c:\Untitled.wmv");
            }
            catch (StorageClientException e)
            {
                Console.WriteLine("Storage client error encountered: " + e.Message);   System.Environment.Exit(1);
            }
        }

Удаление блоба

       protected void DeleteBlob(string blobName)
        {

//получение настройки конфигурации хранилища
            CloudBlobClient blobClient = CloudStorageAccount.FromConfigurationSetting("DataStorage").CreateCloudBlobClient();

//получение ссылки на блоб
            var blob = blobClient.GetBlobReference(blobName);

//удаление блоба в случае его существования
            blob.DeleteIfExists();

        }

Создание и привязка метаданных к контейнеру блобов и блобу

Блобы могут иметь ассоциированные с ними метаданные. Заголовки метаданных могут быть определены по запросу при создании нового контейнера или блоба, или при «привязке» метаданных к уже существующим ресурсам

       protected void AssociateMetadata(string containerName)
        {

//создание коллекции значений ключ-значение

NameValueCollection metadata = new NameValueCollection();

//получение настройки конфигурации хранилища
            CloudBlobClient blobClient = CloudStorageAccount.FromConfigurationSetting("DataStorage").CreateCloudBlobClient();

//получение ссылки на контейнер
            var blobContainer = blobClient.GetContainerReference(containerName);

//определение метаданных
            metadata["id"] = "1";
            metadata["name"] = "mycontainer";

//добавление метаданных в словарь метаданных для контейнера
            blobContainer.Metadata.Add(metadata);

//”коммит” метаданных
            blobContainer.SetMetadata();
//получение ссылки на блоб
            var blob = blobContainer.GetBlobReference("newblob");

//добавление метаданных в словарь метаданных для блоба
            blob.Metadata.Add(metadata);

//”коммит” метаданных
            blob.SetMetadata();

        }

Получение метаданных и свойств контейнера блобов и блоба

        protected void GetMetadata(string containerName)
    {

            CloudBlobClient blobClient =
                CloudStorageAccount.FromConfigurationSetting("DataStorage").CreateCloudBlobClient();
            var blobContainer = blobClient.GetContainerReference(containerName);
        blobContainer.FetchAttributes();
        var metadataContainer = blobContainer.Metadata;
        System.Diagnostics.Trace.WriteLine(metadataContainer["id"]);
        //метаданные для блоба
        var blob = blobContainer.GetBlobReference("newblob");
        blob.FetchAttributes();
        var metadata = blob.Metadata;
        System.Diagnostics.Trace.WriteLine(string.Format("content-type: {0}", blob.Properties.ContentType));
        blob.Properties.ContentType = "image/jpeg";
        System.Diagnostics.Trace.WriteLine(string.Format("content-type after changing: {0}", blob.Properties.ContentType));

    }

Определение прав доступа для контейнера

Класс BlobContainerPublicAccessType является enumeration, состоящим из следующих возможных значений прав доступа:

  • Blob: Публичный доступ на уровне блоба. Анонимные пользователи могут получать контент и метаданные блобов внутри этого контейнера, но не могут получать метаданные контейнера и список блобов внутри него.
  • Container: Публичный доступ на уровне контейнера. Анонимные пользователи могут получать контент и метаданные блоба и контейнера и список блобов внутри контейнера.
  • Off: Анонимный доступ отключен, только владелец аккаунта имеет доступ к каким-либо ресурсам внутри этого контейнера.
    protected void SetBlobContainerPermissions(BlobContainerPublicAccessType publicAccess)
    {
   var blobClient = CloudStorageAccount.FromConfigurationSetting("DataStorage").CreateCloudBlobClient();
        var blobContainer = blobClient.GetContainerReference("mycontainer"); 

//определение разрешений путем создания легковесного объекта
        blobContainer.SetPermissions
            (new BlobContainerPermissions()
                 {
                     PublicAccess = publicAccess
                 });
    }

Управление доступом с помощью Shared Access Signatures и Shared Access Policies

Shared Access Policies и Shared Access Signatures позволяют создать некоторые правила доступа к блобу или контейнеру, определяющие права доступа и период доступа.

Shared Access Policy: Политика определяет время начала действия политики, время истечения и набор разрешений для Shared Access Signatures.

Shared Access Signature: URL, предоставляющий доступ к контейнеру и блобу.

   protected void SetSAS()
    {

        var blobClient = CloudStorageAccount.FromConfigurationSetting("DataStorage").CreateCloudBlobClient();
        var blobContainer = blobClient.GetContainerReference("mycontainer");
//создание объекта разрешений на контейнер
        var permissions = new BlobContainerPermissions();

//добавление политики на “только чтение”
        permissions.SharedAccessPolicies.Add("readonly", new SharedAccessPolicy()
        {
            SharedAccessStartTime = null,
            Permissions = SharedAccessPermissions.Read
        });

//добавление политики на “только запись”
        permissions.SharedAccessPolicies.Add("writeonly", new SharedAccessPolicy()
        {
            SharedAccessStartTime = null,
            Permissions = SharedAccessPermissions.Write
        });

//”коммит” разрешений
        blobContainer.SetPermissions(permissions);

     var blob = blobClient.GetBlobReference("mycontainer/Untitled.wmv");

//получение сигнатуры
        var sas = blob.GetSharedAccessSignature(new SharedAccessPolicy()
                                                    {
                                                        SharedAccessExpiryTime = DateTime.UtcNow.AddDays(5)
                                                    }, "readonly");
        System.Diagnostics.Trace.WriteLine(string.Format("Shared Access Signature for blob {0} is {1}, full link is {0}{1}", blob.Uri.AbsoluteUri, sas));

    }

Копирование и создание снапшотов блобов

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

      protected void CopyAndSnapshotBlob()
        {
            CloudBlobClient blobClient = CloudStorageAccount.FromConfigurationSetting("DataStorage").CreateCloudBlobClient();
            var blobContainer = blobClient.GetContainerReference("mycontainer");
            var srcBlob = blobContainer.GetBlobReference("newblob");

            var newBlob = blobContainer.GetBlobReference("newblobcopy"); ;

            newBlob.CopyFromBlob(srcBlob);

            newBlob.FetchAttributes(new BlobRequestOptions { BlobListingDetails = BlobListingDetails.Metadata });

            newBlob.Metadata["id"] = "2";
            newBlob.Metadata["name"] = "copy of blob"+srcBlob.Metadata["name"];
            newBlob.SetMetadata();
            System.Diagnostics.Trace.WriteLine("Скопированный блоб имеет имя"+newBlob.Metadata["name"]);

            var snapshot = srcBlob.CreateSnapshot();

            System.Diagnostics.Trace.WriteLine("Был создан снапшот для:" + srcBlob.Uri + " в момент времени: " + snapshot.SnapshotTime);

        }

Всё вместе

Учитываем, что у вас уже созданы аккаунт хранилища и сервис для выполнения вашего приложения, а также создан ASP.NET проект с ассоциированным для него Windows Azure облачным проектом.

При программировании собственного облачного проекта не забудьте определить провайдера конфигурации в методе Application_Start (global.asax):

        void Application_Start(object sender, EventArgs e)
        {
            CloudStorageAccount.SetConfigurationSettingPublisher((configName, configSettingPublisher) =>
            {
                var connectionString = RoleEnvironment.GetConfigurationSettingValue(configName);
                configSettingPublisher(connectionString);
            }
    );

А также строку подключения к хранилищу. Для этого:

1. Измените в описании сервиса настройки конфигурации, необходимые для доступа к сервису таблиц Windows Azure: откройте в облачном проекте папку Roles, щелкните правой кнопкой мыши на WebRole и выберите Properties.

http://hpcru.files.wordpress.com/2012/03/image_thumb38.png?w=406&h=138

2. Перейдите на вкладку Settings, нажмите Add Setting и создайте новую настройку конфигурации с именем DataConnectionString. Укажите её тип как Connection String, после чего нажмите на кнопку с троеточием и настройте строку подключения к хранилищу на использование локального эмулятора хранилища – Use storage emulator.

http://hpcru.files.wordpress.com/2012/03/image_thumb39.png?w=396&h=244

3. Нажмите CTRL-S для сохранения изменений.

Примечание: Библиотека StorageClient использует эти настройки для доступа к хранилищу Windows Azure.

DataConnectionString: Это строка подключения к аккаунту Windows Azure, программно используя которую, мы можем осуществить доступ к хранилищу данных и другой функциональности Windows Azure. Эта строка подключения может использовать либо аккаунт Windows Azure в «облаке», либо локальный эмулятор.

Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString: Это строка подключения к серверу Windows Azure, аналогичная DataConnectionString, но отведённая под нужды диагностики.

После этого поместите все вышеприведенные методы в файл Default.aspx.cs (либо любой другой code-behind файл, который хотите) и вставьте следующий код в обработчик события Page_Load:

        protected void Page_Load(object sender, EventArgs e)
        {
            CreateBlobContainer("mycontainer");
            CreateBlobContainerAsync("mycontainerasync");
            DeleteBlobContainer("mycontainerasync");
            DeleteBlob("newblob");
            AddBlob();
            AssociateMetadata("mycontainer");
            GetMetadata("mycontainer");
            SetBlobContainerPermissions(BlobContainerPublicAccessType.Blob);
            SetSAS(); 

            CopyAndSnapshotBlob();         

        }

После запуска в локальном эмуляторе обратите внимание на лог трассировки – в нём вы увидите все сведения, которые выводятся в методах. Кроме этого, вы можете воспользоваться Server Explorer в Visual Studio 2010 для просмотра содержимого вашего локального сервиса хранилища.

http://hpcru.files.wordpress.com/2012/03/image_thumb40.png?w=244&h=133

Диаграмма класса для наглядности того, что должно было получиться в результате:

http://hpcru.files.wordpress.com/2012/03/image_thumb41.png?w=202&h=310