Капля никотина убивает пять минут рабочего времени.
Правда жизни
Вчера мы с Вами обсудили как хранить данные в случае системы в которой хранится много данных. Мы вскольз поговорили с Вами о блобах, теперь давайте обратим на них более пристальное внимание, потому как фича преотличнейшая!
Как хранятся блобы?
Блобы живут в контейнерах, Вы в своем аккаунте можете создавать большое количество контейнеров. Воспринимайте это как папка в которой Вы храните свои файлы, но в такой папке в которой нельзя создаваит другие папки. Тоесть Вы не сможете создать контейнер в контейнере. Не стоит бояться того что Вы не сможете создать аналог файловой системы — хоть я и не понимаю зачем Вам это может понадобиться — но блобы в собсвенных именах могут содержать знак «\» потому Вы сможете сэмулировать файловую систему.
Как доступаться к блобам?
Как уже в прошлом посте я говорил — доступ к любому сервису хранения данных совершается по HTML через REST комманды. Тоесть если у Вас есть контейнер под названием Container1 и в нем файл file1.mpg то аддресс к вашему блобу может выглядеть так:
http://thisisanameofyourstorageservice.blob.core.windows.net/Container1/file1.mpg
В тоже время ваш блоб может называться: folder1/subfolder1/file2.mpg и тогда путь к блобу будет выглядеть так:
http://thisisanameofyourstorageservice.blob.core.windows.net/Container1/folder1/subfolder1/file2.mpg
Но, не беспокойтесь, Вам не прийдется досутпаться к блобам через урлу:) Есть куда более цивилизованные методы о которых мы поговорим немного позже.
А давайте заведет свой аккаунт хранения данных!
Теперь давайте залогинемся на наш ажур портал и создадим новые сервисы хранения данных:
Нажимаем «New Storage Account», тут мы даем название сервису хранения данных а так же выбираем географический регион в котором наши данные будут размещенны. Тоесть, если мы выберем регион Европу — то все наши данные будут сохраненны в датацентре который размещен в Европе.
По умолчанию аддресс к сервисам хранения данных выглядит так:
http://.blob.core.windows.net/
http://.queue.core.windows.net/
http://.table.core.windows.net/
При использовании имени сервисов: newstoragename , адреса будут выглядеть так:
http://newstoragename.blob.core.windows.net/
http://newstoragename.queue.core.windows.net/
http://newstoragename.table.core.windows.net/
Теперь давайте поговорим немного о контейнерах. К контейнеру надо относиться как к папке самого высшего уровня — или как к диску. Вы не можете создать блоб напрямую в сервисы хранения данных — это возможно сделать только в контейнер. Вообще не очень круто будет, если любой сможет доступаться к нашим блобам, а устанавливать права доступа к каждому блобу — это ещё тот «мартышкин труд», потому права доступа к блобам выставляются на уровне контейнеров. Контейнеры бывают двух видов:
1. Приватные контейнеры. Для того чтобы считать данные с этого блоба — необходимо знать ключ с помощью которого можна доступаться к данным этого контейнера.
2. Только чтение для контейнера и только чтение для блоба. Если выставить только чтение для контейнера — любой сможет доступаться и читать данные блобов в контейнере. Если поставить только чтение для блоба — пользователи смогут читать данные блоба, но не смогут смотреть какие блобы вообще есть в контейнере.
Помните, как для разработки интсрументарий Ажура эмулирует для нас сервисы хранения данных?
Важно понимать — что сервисы хранения данных эмулированные и сервисы хранения данных на Ажуре — две разные вещи. С эмулятором, кроме ограничений которые я приводил раньше -у нас отсутствует репликация. Ну и ещё много вкусностей. Замечательное в этом все то, что если мы тестируем наше приложение на эмуляторе, то чтобы наше приложения заработало в продакшене — нам стоит всего лишь поменять одну строчку в настройках сервиса. Но об этом попозже:)
Эмулятор может запустить как сама студия, так и вы руками. Сделать это можно с помощью такой комманды:
C:\Program Files\Windows Azure SDK\v1.3\bin\devstore\DSService.exe
Чтобы выключить, можна использовать такую комманду:
C:\Program Files\Windows Azure SDK\v1.3\bin\devstore\DSService.exe /shutdown
Естественно расположения может меняться в зависимости от установки Azure SDK.
А теперь немного покодим!
Естественно чтобы начать кодить, нам необходимо каким то образом доступаться к сервисам хранения данных. Делается это очень просто — мы всего лишь обязанны задать компоненте корректный конекшен стринг к нашим сервисам. Так как пока мы не работаем в реальной среде , мы будем использовать эмулятор. Для того чтобы доступиться к эмулятору — есть всего лишь один аккаунт, и он одинаковый для всех:
storage account name: devstoreaccount1
Shared Key:Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGM
Gw==
Эти два парметра будут одинаковы во всех случаях и на любом компьютере. Естественно когда вы будете использовать сервисы хранения данных на Ажуре — эти параметры будут совершенно другие, но пока что есть — то есть:)
Путь к нашему блобу с использыванием эмулятора будет иметь такой вид:
http://127.0.0.1:10000/devstoreaccount1/Container1/file1.mpg
Формализировать его можно так:
http://127.0.0.1:10000/<StorageAccountName>/<Container>/<BlobName>
Для того чтобы доступаться к сервисам хранения данных с веб роли, нам вначале необходимо иметь конекшен стрингу к этому сервису. Для того чтобы создать такую строчку, давайте посмотрим на настройки веб роли. В настройках веб роли, выберите добавить настройку, и задайте ей тип — ConnectionString. После чего, в значение этой настройки выберите UseDevelopmentStorage. Все, настройка есть!
Если посмотреть на xml файл, то Вы увидите что-то вроде такого:
<Role name="TestRole"> <Instances count="1" /> <ConfigurationSettings> <Setting name="Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString" value="UseDevelopmentStorage=true" /> <Setting name="testConnectionString" value="UseDevelopmentStorage=true" /> </ConfigurationSettings> </Role>
При использовании реальных сервисов хранения данных эта настройка имела бы следующий вид:
<Role name="TestRole"> <Instances count="2" /> <ConfigurationSettings> <Setting name="Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString" value="UseDevelopmentStorage=true" /> <Setting name="testConnectionString" value="DefaultEndpointsProtocol=https;AccountName=accountname;AccountKey=accountKey" /> </ConfigurationSettings> </Role>
Только вместо accountname и accountkey — название ваших сервисов хранения данных и ключ доступа к ним же.
Итак, настройка с конекшен стрингом к нашым сервисам хранения данных есть — давайте туда что нибудь запишем!
Для разогрева создадим обычную веб роль, и на страничке по умочанию добавим кнопку. Выглядит это приблизительно так:
<asp:Content ID="HeaderContent" runat="server" ContentPlaceHolderID="HeadContent"> </asp:Content> <asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent"> <ContentTemplate> <asp:Button ID="Button1" runat="server" Text="Button" OnClick="ButtonClick" /> </ContentTemplate> </asp:Content>
В обработке клика на кнопку, давайте добавим функционал создания каталога:
/// <summary> /// Handles the Click event of the Button1 control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param> protected void Button1_Click(object sender, EventArgs e) { SetConfiguration(); CloudStorageAccount account = CloudStorageAccount.FromConfigurationSetting("testConnectionString"); CloudBlobClient blobClient = account.CreateCloudBlobClient(); CloudBlobContainer container = blobClient.GetContainerReference("newcontainer"); container.Create(); }
Как Вы заметили, я вызываю метод SetConfiguration(), выглядит он так:
/// <summary> /// Sets the configuration. /// </summary> private void SetConfiguration() { CloudStorageAccount.SetConfigurationSettingPublisher((configName, configSetter) => { // Provide the configSetter with the initial value configSetter(RoleEnvironment.GetConfigurationSettingValue(configName)); RoleEnvironment.Changed += (sender, arg) => { if (arg.Changes.OfType<RoleEnvironmentConfigurationSettingChange>() .Any((change) => (change.ConfigurationSettingName == configName))) { // The corresponding configuration setting has changed, propagate the value if (!configSetter(RoleEnvironment.GetConfigurationSettingValue(configName))) { // In this case, the change to the storage account credentials in the // service configuration is significant enough that the role needs to be // recycled in order to use the latest settings. (for example, the // endpoint has changed) RoleEnvironment.RequestRecycle(); } } }; }); }
Это большая загадка для меня, почему я должен его дергать каждый раз, но если не использовать этот метод то получить досутп к сервисам хранения данных неполучиться. В идеале, получать настройки лучше через хелпер класс, в котором будет реализован этот метод и вызываться будет только один раз. Только для демонстрации я его ичпользовал таким некрасивым образом.
Итак, давайте теперь разберемся что мы сделали:)
CloudStorageAccount account = CloudStorageAccount.FromConfigurationSetting("testConnectionString");
Тут мы создали объект который может работать с сервисами хранения данных в Ажуре или на эмуляторе. Как видим конекшен стрингу он подтягивает с файла конфигурации веб роли.
Дальше нам необходимо создать клиент который умеет работать с блобами:
CloudBlobClient blobClient = account.CreateCloudBlobClient();
Вообще с этим объектом мы можем делать много интересных вещей, таких как:
— Возвращение списка контейнеров
— Получение ссылки на специфический контейнер
— Список блобов
— Ссылка на спецефический блоб
После этого нам нужно получить ссылку на контейнер, даже если он не существует:
CloudBlobContainer container = blobClient.GetContainerReference("newcontainer");
Вот тут будьте внимательны — контейнер может иметь в своем названии только буквы в нижнем регистре. У меня поиск решения почему моя аппликация не работает украло пол часа времени:) Не повторяйте моих ошибок.
Ну и последнюю строчку я думаю объяснять не иммет смысла, так как и так все понятно. Кстати, если запустите приложение ещё раз — получите ошибку что такой контейнер уже существует. Потому будьте аккуратней.
При создании контейнера — автоматически приватные разрешения установлены на контейнер, поэтому если вы хотите оставить возможность пользователям которые не знают ключа к контейнеру смотреть в нем файлы — настройка должны быть установлена на публичное чтение.
А ещё с этим объектом можно совершать такие действия:
-Создание контейнера
-Удаление контейнера
-Метаданные
-Свойства контейнера
-Получить или установить разрешнеия на контейнер
-Получить список блобов
-получение специфического блоба
Давайте посмотрим как мы можем получить лист контейнеров:
/// <summary> /// Handles the Click event of the Button1 control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param> protected void Button1_Click(object sender, EventArgs e) { SetConfiguration(); CloudStorageAccount account = CloudStorageAccount.FromConfigurationSetting("testConnectionString"); CloudBlobClient blobClient = account.CreateCloudBlobClient(); var list = blobClient.ListContainers(); }
Удаление контейнера
/// <summary> /// Handles the Click event of the Button1 control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param> protected void Button1_Click(object sender, EventArgs e) { SetConfiguration(); CloudStorageAccount account = CloudStorageAccount.FromConfigurationSetting("testConnectionString"); CloudBlobClient blobClient = account.CreateCloudBlobClient(); CloudBlobContainer container = blobClient.GetContainerReference("newcontainer"); container.Delete(); }
В следующем посты мы с Вами наконец-то поговорим именно про блобы:)
Уведомление: ??????????? ????????? ?? ????????? ? ???????? Microsoft ?? ??????? ????? – ?????? 2011 - MSDN Blogs
Уведомление: Технические материалы по продуктам и решениям Microsoft на русском языке – апрель 2011 | Alexander Knyazev: блог