Основы хранилища 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
Необходимо учитывать различия, имеющиеся между хранилищем блобов в локальном эмуляторе и хранилищем блобов в облаке.
- Эмулятор поддерживает блобы до 2 Гб
- Если происходит два запроса по загрузке блока в блоб, которого еще не существует в хранилище, один запрос создаст блоб, второй может вернуть код возврата 409 (Conflict) с кодом ошибки BlobAlreadyExists.
- В эмуляторе отсутствует поддержка Microsoft.WindowsAzure.StorageClient.CloudBlobClient.SetServiceProperties(Microsoft.WindowsAzure.StorageClient.Protocol.ServiceProperties).
Операции, доступные для управления блобами в хранилище 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