Цель данной лекции – получить представление об архитектуре Windows Azure
Платформа Windows Azure – это модель Платформа как Сервис, которая предполагает запуск приложений на серверах и связанной сетевой инфраструктуре, размещенной в центрах обработки данных Microsoft и имеющей доступ в Интернет. Платформа состоит из мастшабируемой "облачной" операционной системы, фабрики хранения данных и связанных сервисов доставки через физические или логические (виртуализация) экземпляры Windows Server 2008. Комплект средств разработки Windows Azure (SDK) обеспечивает разработку версии "облачных сервисов", также хорошо, как инструменты и интерфейсы прикладного программирования (API), необходимые для разработки, разворачивания и управления масштабируемых сервисов в Windows Azure, включая шаблоны приложений Azure для Visual Studio 2008 и 2010. На рисунке 6.1 изображены компоненты основа "облачной" платформы и компоненты разработчика.
Согласно Microsoft, при использовании Azure Вы получаете:
(рис 6.1) Компоненты платформы Windows Azure и Комплекта средств разработки
Экономическая обстановка Microsoft во время выпуска платформы Azure акцентировала внимание на снижении затрат, что является основным поводом для использования Azure мелкими, средними и крупными ИТ отделами.
Microsoft разработали платформу Azure, позволив .NET разработчикам усилить их опыт создания в Visual Studio 2008 (и выше) ASP.NET веб приложений и Windows Communication Framework (WCF) сервисов. Проекты веб приложений запускаются в изолированной версии Internet Information Services (IIS) 7. Веб приложения и веб сервисы запускаются в частично доверенном механизме защиты, позволяющем ограничивать доступ коду к ресурсам компьютера (Code Access Security), который приблизительно соответсвует среднему уровню доверия ASP.NET и ограничивает доступ к некоторым ресурсам операционной системы. Комплект средств разработки Windows Azure (Март 2009) позволяет использоваться полный доступ к ресурсам компьютера для запуска не .NET кода, использования .NET библиотек, которые требуют полного доверия и процесс обработки взаимодействия, используя программные каналы (Pipe). Microsoft обещает поддержку запуска программного кода Ruby, PHP и Python в "облачной" платформе. Исходный вариант платформы разработки был ограничен средой программирования Visual Studio 2008 и выше с планом на поддержку инструментов Eclipse. Платформа Windows Azure поддерживает веб стандарты и протоколы включая SOAP, HTTP, XML, Atom и AtomPub.
Исходной точкой входа для разработчиков Azure для размещения ASP.NET приложений в облако является портал Windows Azure по адресу https://windows.azure.com/Cloud/Provisioning/Default.aspx. Портал требует входа с использованием Windows Live ID. Предварительная версия Azure (Community Technical Previews ,
Windows Azure, которая включает:
SQL Azure Live службы, которые включают:
Live сервисы: существующие интерфейсы прикладного программирования не являются частью предварительной версии и не требуют токена. С начала 2009 года Windows Azure токен дает право на одну учетную запись Hosted Service, две учетные записи для Storage. Вы запрашиваете токены Azure через страницу Microsoft Connect, на которую можно попасть со страницы портала.
На рисунке 6.1 показана страница учетной записи, которая содержит ссылки на страницы настроек и управления SQL Azure, сервисами .NET и Live сервисами. Эта страница также позволяет вам получать Azure и Live Framework
Предварительная версия марта 2009 года включает геолокацию, которая позволяет владельцам учетных записей выбрать центры обработки данных для расположения
Вы можете вставить GUID полученные в сообщении от члена команды Azure в текстовое окно Resource Token ID и нажать Claim Token для добавление еще одной или больше точки входа для подходящего объекта или нескольких объектов в список.
Если вы хотите разрабатывать веб сайты с поддержкой Live Framework или Mesh (программный комплекс для синхронизации данных в кроссплатформенных средах разработанный компанией Microsoft) веб приложений, необходимо запросить токен Live Framework по email meshctpe@microsoft.com. После того, как вы получите Live Framework токен, вы можете скачать и установить текущие версии Live Framework SDK и Live Framework Tools для Visual Studio по ссылкам указанным на странице http://dev.live.com/liveframework/sdk/. Вы должны оплатить Live Framework токен для того, чтобы скачать Live SDK и дополнительные инструменты. Нет необходимости использовать учетную запись Windows Azure для тестирования Azure
Хранилище Windows Azure Storage обеспечивает разработчикам возможность хранения данных в облаке. Приложение может выполнять доступ к своим данным в любой момент времени из любой точки планеты, хранить любой объем данных и как угодно долго. При этом данные гарантированно не будут повреждены и утеряны. Windows Azure Storage предлагает богатый набор абстракций данных:
Windows Azure Table - структурированное хранилище, которе поддерживает высокомасштабируемые таблицы в облаке, которые могут содержать миллиарды сущностей и терабайты данных. По мере увеличения трафика, система будет эффективно масштабироваться, автоматически подключая тысячи серверов. Структурированное хранилище реализовано в виде таблиц (Tables), в которых располагаются сущности (Entities), содержащие ряд именованных свойств (Properties). Вот некоторые из основных характеристик Windows Azure Table:
Рассмотрим модель данных таблицы Windows Azure Table:
<имяУчетнойЗаписи>.table.core.windows.net.Таблица имеет гибкую схему. Windows Azure Table отслеживает имя и типизированное значение каждого свойства каждой сущности. Приложение может моделировать фиксированную схему на стороне клиента, обеспечивая одинаковый набор свойств для всех создаваемых сущностей.
Рассмотрим некоторые дополнительные сведения о сущностях:
| Тип свойства | Описание |
|---|---|
| Binary | Массив байтов размером до 64 КБ. |
| Bool | Булево значение. |
| DateTime | 64-разрядное значение, представляющее время в формате UTC. Поддерживаемый диапазон значений: от 1/1/1600 до 12/31/9999. |
| Double | 64-разрядное значение с плавающей точкой. |
| GUID | 128-разрядный глобально уникальный идентификатор. |
| Int | 32-разрядное целое значение. |
| Int64 | 64-разрядное целое значение. |
| String | 16-разрядное UTF-кодированное значение. Размер строковых значений может быть до 64 КБ. |
Windows Azure Table обеспечивает возможность масштабирования таблиц до тысяч узлов хранения через распределение сущностей в таблице. При распределении сущностей желательно обеспечить, чтобы сущности, входящие в одно множество, располагались в одном узле хранения. Приложение формирует эти множества соответственно значениям свойства PartitionKey сущностей.
Приложениям должна быть известна рабочая нагрузка каждой отдельно взятой секции. Для обеспечения желаемых результатов тестирование должно моделировать максимальную рабочую нагрузку.
(рис 6.2) Примеры секций
На рисунке выше представлена таблица, содержащая множество версий документов. Каждая сущность данной таблицы соответствует определенной версии определенного документа. В этом примере ключом
Хорошая масштабируемость системы хранения достигается за счет распределения секций по множеству узлов хранения.
Система отслеживает характер использования секций и автоматически равномерно распределяет эти секции по всем узлам хранения. Это позволяет системе и приложению масштабироваться соответственно количеству запросов к таблице. То есть если некоторые секции запрашиваются больше других, система автоматически разнесет их на несколько узлов хранения, таким образом, распределяя трафик между множеством серверов. Однако секция, т.е. все сущности, имеющие одинаковый ключ секции, будут обслуживаться как один узел. Но даже несмотря на это, объем данных в рамках секции не ограничен емкостью хранилища одного узла хранения.
Сущности одной секции хранятся вместе. Это обеспечивает наиболее эффективную обработку запросов к секции. Более того, в этом случае приложение может использовать все преимущества эффективного кэширования и других оптимизаций производительности, обеспечиваемых расположением данных в секции.
В примере выше секцию образуют все версии одного документа. Таким образом, для извлечения всех версий данного документа необходимо выполнить доступ всего к одной секции. Чтобы получить все версии документов, измененные до 5/30/2007, придется запрашивать несколько секций, что будет не так эффективно и более ресурсоемко, поскольку по запросу должны будут проверяться все секции, которые к тому же могут располагаться на разных узлах хранения.
Выбор ключа секции важен с точки зрения обеспечения эффективного масштабирования приложения. При этом необходимо найти компромисс между размещением сущностей в одной секции, что обеспечивает большую эффективность запросов, и масштабируемостью таблицы, поскольку, чем больше секций в таблице, тем проще для Windows Azure Table распределить нагрузку между множеством серверов.
Для наиболее частых и критичных по времени ожидания запросов PartitionKey должен быть включен как часть выражения запроса. Запрос, в котором указан PartitionKey, будет намного эффективнее, поскольку в этом случае просматриваются сущности только одной секции. Если при выполнении запроса PartitionKey не указан, в поисках необходимых сущностей просматриваются все
Далее представлены некоторые советы и рекомендации по выбору PartitionKey для таблицы:
Теперь, когда приложение имеет набор
MSDN, мы обсудим, как оптимизировать использование Windows Azure Table и предотвратить возникновение таких ошибок в вашем приложении.
Также можно проанализировать расширяемость выбранных ключей, особенно если на момент их выбора нет точных сведений о характеристиках пользовательского трафика. В этом случае важно выбирать ключи, которые можно легко расширять для обеспечения более тонкого секционирования. Далее в данном документе приводится подробный пример этого.
Для таблиц и сущностей поддерживаются следующие базовые операции:
Для работы с таблицами в .NET-приложении можно просто использовать ADO.NET Data Services.
В следующей таблице приведен список предлагаемых API. Поскольку применение ADO.NET Data Services в итоге сводится к передаче REST-пакетов, приложения могут использовать REST напрямую. Кроме того, что REST обеспечивает возможность доступа к хранилищу посредством не-.NET языков, он также позволяет реализовывать более тонкое управление сериализацией/десериализацией сущностей, что пригодится при работе с такими сценариями, как наличие разных типов сущностей или более чем 255 свойств в таблице и т.д.
В приведенных ниже примерах описываются операции с таблицей "Blogs". В этой таблице хранятся блоги для приложения MicroBlogging.
В приложении MicroBlogging есть две таблицы: Channels (Каналы) и Blogs (Блоги). Имеется список каналов, блоги публикуются в определенном канале. Пользователи подписываются на каналы и ежедневно получают новые блоги этих каналов.
В данном примере рассмотрим только таблицу Blogs и приведем примеры следующих операций с ней:
Схема таблицы описывается как C#-класс. Такую модель использует ADO.NET Data Services. Схема известна только клиентскому приложению и упрощает доступ к данным. Сервер схему не применяет.
Рассмотрим описание сущностей Blog, хранящихся в таблице Blogs. Каждая сущность блога содержит следующие данные:
Во-первых, обратите внимание, что для таблицы определен PartitionKey, представляющий имя канала, частью которого является блог, и в качестве RowKey используется дата размещения блога. PartitionKey и RowKey – ключи таблицы Blogs, они объявляются посредством атрибута класса DataServiceKey (Ключ сервиса данных). То есть таблица Blogs секционирована по именам каналов (ChannelName). Это позволяет приложению эффективно извлекать самые недавние блоги канала, на который подписан пользователь. Кроме ключей, в качестве свойств объявлены характерные для пользователя атрибуты. Все свойства имеют открытые (public) методы считывания и присвоения значения и хранятся в таблице Windows Azure Table. Итак, в примере ниже:
[DataServiceKey("PartitionKey", "RowKey")]
public class Blog
{
// ChannelName
public string PartitionKey { get; set; }
// PostedDate
public string RowKey { get; set; }
// Определяемые пользователем свойства
public string Text { get; set; }
public int Rating { get; set; }
public string RatingAsString { get; }
protected string Id { get; set; }
}
Далее рассмотрим, как создать таблицу Blogs для учетной записи хранилища. Создание таблицы аналогично созданию сущности в основной таблице "Tables". Эта основная таблица определена для каждой учетной записи хранилища, и имя каждой таблицы, используемой учетной записью хранения, должно быть зарегистрировано в основной таблице. Описание класса основной таблицы приведено ниже, где свойство TableName (Имя таблицы) представляет имя создаваемой таблицы.
[DataServiceKey("TableName")]
public class TableStorageTable
{
public string TableName { get; set; }
}
Фактическое создание таблицы происходит следующим образом:
// Uri сервиса: "http://<Account>.table.core.windows.net/"
DataServiceContext context = new DataServiceContext(serviceUri);
TableStorageTable table = new TableStorageTable("Blogs");
// Создаем новую таблицу, добавляя новую сущность
// в основную таблицу "Tables"
context.AddObject("Tables", table);
// результатом вызова SaveChanges является отклик сервера
DataServiceResponse response = context.SaveChanges();
serviceUri – это uri сервиса таблицы, http://<Здесь указывается имя учетной записи>.table.core.windows.net/. DataServiceContext (Контекст сервиса данных) – один из основных классов сервиса данных ADO.NET, представляющий контекст времени выполнения для сервиса. Он обеспечивает API для вставки, обновления, удаления и запроса сущностей с помощью либо LINQ, либо RESTful URI и сохраняет состояние на стороне клиента.
Рассмотрим вставку элемента Blog. Чтобы вставить сущность, приложение должно выполнить следующее.
DataServiceContext, который представляет подключение к серверу в сервисе данных ADO .NET для вашей учетной записи хранилища.SaveChanges (Сохранить изменения) объекта DataServiceContext для отправки запроса серверу. Это обеспечивает отправку на сервер HTTP-запроса с сущностью в XML-формате ATOM.Далее представлены примеры кода для перечисленных выше операций:
Blog blog = new Blog {
PartitionKey = "Channel9", // ChannelName
RowKey = DateTime.UtcNow.ToString(), // PostedDate
Text = "Hello",
Rating = 3
};
serviceUri = new Uri("http://<account>.table.core.windows.net");
var context = new DataServiceContext(serviceUri);
context.AddObject("Blogs", blog);
DataServiceContext response = context.SaveChanges();
Запрос сущностей выполняется с помощью встроенного в C# языка запросов LINQ (Language Integrated Query). В данном примере извлечем все блоги, рейтинг которых равен 3.
При обработке запроса (например, с помощью выражение foreach), он передается на сервер. Сервер отправляет результаты в XML-формате ATOM. Клиентская библиотека ADO .NET Data Services десериализует результаты в C#-объекты, после чего они могут использоваться приложением.
var serviceUri = new Uri("http://<account>.table.core.windows.net");
DataServiceContext context = new DataServiceContext(serviceUri);
// LINQ-запрос с использованием DataServiceContext для выбора
// из таблицы Blogs всех сущностей блогов, для которых rating = 3
var blogs =
from blog in context.CreateQuery<blog>("Blogs")
where blogs.Rating == 3
select blog;
// запрос отправляется на сервер и выполняется
foreach (Blog blog in blogs) { }
Обновление сущности выполняется следующим образом.
DataContext (Контекст данных), свойству MergeOption (Вариант объединения) которого задается значение OverwriteChanges (Перезапись изменений) или PreserveChanges (Сохранение изменений), как описывается в разделе 4.8. Это обеспечивает правильную обработку ETag для каждого извлекаемого объекта.LINQ DataContext получает сущность, которая будет обновляться. Извлечение ее с сервера гарантирует обновление ETag в сущностях, отслеживаемых контекстом, и то, что при последующих обновлениях и удалениях в заголовке if-match будет использоваться обновленный ETag. Меняем C#-объект, представляющий сущность.DataContext для обновления. Использование того же DataContext гарантирует автоматическое повторное использование ETag, полученного ранее для этого объекта.SaveChanges для отправки запроса на сервер.Blog blog =
(from blog in context.CreateQuery<blog>("Blogs")
where blog.PartitionKey == "Channel9"
blog.RowKey == "Oct-29"
select blog).FirstOrDefault();
blog.Text = "Hi there";
context.UpdateObject(blog);
DataServiceResponse response = context.SaveChanges();
4.7 Удаление Blog
Удаление сущности аналогично ее обновлению. Для этого извлекаем сущность с помощью DataServiceContext и вызываем для содержимого вместо метода UpdateObject метод DeleteObject (Удалить объект).
// Получаем объект Blog для ("Channel9", "Oct-29")
context.DeleteObject(blog);
DataServiceResponse response = context.SaveChanges();
Рассмотрим рекомендации по работе с DataServiceContext:
DataServiceContext не обеспечивает безопасность потоков, поэтому он не может использоваться совместно разными потоками, а также имеет непродолжительное время существования.DataServiceContext не является объектом с длительным временем жизни. Вместо того, чтобы использовать один DataServiceContext в течение всей жизни потока, рекомендуется создавать объект DataServiceContext каждый раз, когда возникает необходимость выполнить ряд транзакций с WindowsAzureTable, и затем удалять этот объект.DataServiceContext и возникает сбой при выполнении SaveChanges, сведения об операции, давшей сбой, сохраняются в DataServiceContext. При последующем вызове SaveChanges попытка выполнить эту операцию повторяется.DataServiceContext имеет свойство MergeOption, которое используется для управления тем, как DataServiceContext обрабатывает отслеживаемые сущности. Возможные значения:AppendOnly (Только добавление): Это значение по умолчанию, при использовании которого DataServiceContext не загружает экземпляр сущности с сервера, если он уже имеется в его кэше.OverwriteChanges: DataServiceContext всегда загружает экземпляр сущности с сервера и перезаписывает предыдущий вариант сущности, т.е. обеспечивает соответствие экземпляра сущности ее текущему состоянию.PreserveChanges: Если экземпляр сущности существует в DataServiceContext, он не загружается из постоянного хранилища. Все изменения, вносимые в свойства объектов в DataServiceContext, сохраняются, но ETag обновляется, поэтому данную опцию следует использовать при необходимости восстановления после ошибок совместного доступа с нежесткой блокировкой.NoTracking (Без отслеживания): DataServiceContext не отслеживает экземпляры сущностей. Обновление сущности
в контексте без отслеживания реализуется с помощью Etag, который обновляется посредством AttachTo. Этот вариант
не рекомендуется к применению.context.AttachTo("Blogs", blog, "etag to use");
context.UpdateObject(blog);
context.SaveChanges();
Когда MergeOption контекста задано значение AppendOnly и объект DataServiceContext уже отслеживает сущность в результате предыдущей операции извлечения или добавления, повторное извлечение сущности с сервера не приведет к обновлению отслеживаемой сущности в контексте. Таким образом, если сущность на сервере была изменена, последующие обновления/удаления приведут к сбою необходимых условий ( PreCondition ). В примере кода раздела 5 MergeOption задано значение PreserveChanges, которое обеспечивает, что сущность будет загружаться с сервера всегда.
Результатом всех рассматриваемых выше операций является передача HTTP-сообщений на и с сервера. Приложение может отказаться от использования клиентской библиотеки .NET и работать на уровне HTTP/REST.
Рассмотрим параллельные обновления. Для обновления сущности необходимо выполнить следующие операции.
Предположим, два процесса, выполняющихся параллельно, пытаются обновить одну и ту же сущность. Поскольку шаги 1 и 2 не являются неделимыми, на любом из них может возникнуть ситуация внесения изменений в уже устаревшую версию сущности. Для решения этой проблемы Windows Azure Table использует нежесткую блокировку.
ETag HTTP.UPDATE (обновить) на сервер, он отправляет на него этот ETag в виде заголовка If-Match.ETag в заголовке If-Match, изменение принимается, и хранящаяся на сервере сущность получает новую версию. Эта новая версия возвращается клиенту как заголовок ETag.ETag в заголовке If-Match, изменение отклоняется, и клиенту
возвращается HTTP-ошибка "precondition failed" (необходимое условие не выполнено).При получении ошибки "precondition failed" типовым поведением клиентского приложения будет повторение всей операции, как показано в фрагменте кода ниже.
При использовании клиентской библиотеки .NET приложение получает HTTP-код ошибки в виде исключения DataServiceRequestException.
В примере ниже два разных клиента выполняют один и тот же код для изменения текста. Эти два клиента пытаются задать Text разные значения.
ETag, например, "v1". Оба клиента полагают, что предыдущая версия сущности – "v1".Text.UpdateObject и SaveChanges."If-Match: v1".If-Match с версией сущности. Они совпадают."v2"."ETag:v2".If-Match с версией сущности. Они не совпадают, поскольку версия сущности уже изменена на "v2", тогда как в запросе указывается версия "v1".// Задаем такой вариант объединения, который обеспечивает
// сохранение обновлений, но позволяет обновление etag.
// По умолчанию применяется значение AppendOnly, при котором
// уже отслеживаемая сущность не перезаписывается значениями,
// полученными с сервера, в результате чего в случае изменения
// сущности на сервере используется недействительный etag.
context.MergeOption = MergeOption.PreserveChanges;
Blog blog =
(from blog in context.CreateQuery<blog>(quot;Blogsquot;)
where blog.PartitionKey == quot;Channel9quot;
blog.RowKey == quot;Oct-29quot;
select blog).FirstOrDefault();
blog.Text = quot;Hi there againquot;;
try
{
context.UpdateObject(blog);
DataServiceResponse response = context.SaveChanges();
}
catch (DataServiceRequestException e)
{
OperationResponse response = e.Response.First();
if (response.StatusCode == (int)HttpStatusCode.PreconditionFailed)
{
// выполняем запрос объекта повторно, чтобы получить
// последний etag, и проводим обновление
}
}
Для безусловного обновления сущности приложение выполняет следующее:
DataServiceContext или, в случае использования существующего контекста, отсоединяет объект, как демонстрирует пример ниже."*" как новое значение ETag.SaveChanges.// задаем опцию объединения, разрешающую перезапись,
// чтобы обеспечить возможность обновления отслеживаемой сущности
context.Detach(blog);
// Присоединяем сущность к контексту, используя имя таблицы, сущность,
// которая должна быть обновлена, и "*" как значение etag.
context.AttachTo("Blogs", blog, "*");
blog.Text = "Hi there again";
try
{
context.UpdateObject(blog);
DataServiceResponse response = context.SaveChanges();
}
catch (DataServiceRequestException e)
{
// Обработка ошибки, но в данном случае формировнание ошибки PreCondition невозможно
}
Для запросов, которые могут возвращать большое количество результатов, система обеспечивает два механизма:
Take(N).Система поддерживает функцию возвращения первых N соответствующих запросу сущностей. Например, если программа разрабатывается на .NET, для извлечения первых N сущностей (в данном примере это первые 100 сущностей) можно использовать LINQ-функцию Take(N).
serviceUri = new Uri("http://<account>.table.core.windows.net");
DataServiceContext svc = new DataServiceContext(serviceUri);
var allBlogs = context.CreateQuery<blog>("Blogs");
foreach (Blog blog in allBlogs.Take(100))
{
// выполняем некоторые операции с каждым блогом
}
Аналогичная функциональность поддерживается в интерфейсе REST через опцию строки запроса $top=N. Например, запрос "GET http://<UriСервиса>/Blogs?$top=100" обеспечил бы возвращение первых 100 сущностей, соответствующих запросу. Фильтрация выполняется на сервере, поэтому в ответе клиенту может быть передано максимум 100 сущностей.
REST ).В любом из этих случаев ответ будет включать маркер продолжения в виде специального заголовка. Для запроса к вашим сущностям используются такие заголовки:
x-ms-continuation-NextPartitionKeyx-ms-continuation-NextRowKeyЕсли клиент получил эти значения, он должен передать их со следующим запросом в виде опций HTTP-запроса; во всем остальном запрос остается неизменным. Это обеспечит возвращение следующего набора сущностей, начинающегося с места, обозначенного маркером продолжения.
Последующий запрос выглядит следующим образом:
http://<UriСервиса>/Blogs?<исходныйЗапрос>NextPartitonKey=<некотороеЗначение>NextRowKey=<другоеЗначение>
Это повторяется до тех пор, пока клиентом не будет получен ответ без маркера продолжения, что свидетельствует об извлечении всех соответствующих запросу результатов.
Маркер продолжения должен рассматриваться как непрозрачное значение. Оно указывает на точку начала следующего запроса и может не соответствовать фактической сущности в таблице. Если в таблицу добавляется новая сущность, так что Key (новая сущность) > Key (последняя сущность, извлеченная запросом), но Key (новая сущность) < "Маркера продолжения", тогда эта новая сущность не будет возвращена повторным запросом, использующим маркер продолжения. Но новые сущности, добавленные так, что Key(новая сущность) > "Маркера продолжения", войдут в результаты, возвращаемые последующими использующими маркер продолжения запросами.
Теперь рассмотрим модель согласованности, обеспечиваемую Windows Azure Table.
В рамках одной таблицы система обеспечивает гарантии транзакции ACID для всех операций вставки/обновления/удаления для одной сущности.
Для запросов в рамках отдельной секции выполняется изоляция моментального снимка. Запрос обеспечивается согласованным представлением секции с момента его начала и в течение всей транзакции. Моментальный снимок обеспечивает следующее:
Изоляция моментального снимка поддерживается только в рамках секции и в рамках одного запроса. Система не поддерживает изоляцию моментального снимка для нескольких секций таблицы или других фаз запроса.
Приложения отвечают за сохранение согласованности между множеством таблиц.
В примере MicroBlogging использовалось две таблицы: Channels и Blogs. Приложение выполняет согласование таблиц Channels и Blogs. Например, когда канал удаляется из таблицы Channels, приложение должно удалить соответствующие блоги из таблицы Blogs.
Сбои могут возникать в моменты синхронизации состояния множества таблиц. Приложение должно уметь обрабатывать такие сбои и иметь возможность возобновлять работу с момента, на котором она была прервана.
В предыдущем примере, когда канал удаляется из таблицы каналов, приложение должно также удалить все блоги этого канала из таблицы Blogs. В ходе этого процесса могут возникать сбои приложения. Для обработки таких сбоев приложение может сохранять транзакцию в Windows Azure Queues, что позволяет пользователю возобновить операцию удаления канала и всех его блогов даже в случае сбоя.
Вернемся к примеру с таблицами Channels и Blogs. Channels имеет следующие свойства: Name (Имя) как PartitionKey, пустая строка как RowKey, Owner (Владелец), CreatedOn (Дата создания). И Blogs имеет свойства Channel Name (Имя канала) как PartitionKey, CreatedOn как RowKey, Title (Название), Blog, UserId. Теперь, когда канал удален, необходимо обеспечить, чтобы все ассоциированные с ним блоги также были удалены. Для этого выполняем следующие шаги:
"DeleteChannelAndBlogs" (Удаление каналов и блогов)."DeleteChannelAndBlogs".DeleteChannelAndBlogs, задавая для извлеченного элемента очереди время невидимости
в течение N секунд. При этом элемент, определяющий имя канала, который должен быть удален, изымается. Если роль работника удаляет элемент очереди
в течение этих N секунд, данный элемент будет удален из очереди. Если нет, элемент станет вновь видимым и доступным для использования рабочей ролью.
При извлечении элемента рабочая роль делает следующее:Channels помечает канал как недействительный, чтобы с этого момента никто не мог выполнять чтение из него.Blogs все записи, для которых PartitionKey = "имени канала", указанному в элементе очереди.Channels.Если в ходе выполнения, например, шага 4, возникает какой-либо сбой, производится аварийное завершение рабочего процесса, при этом элемент очереди не удаляется из нее. Таким образом, как только соответствующий элемент очереди станет снова видимым (т.е. когда истечет время, заданное как время ожидания видимости), это сообщение будет вновь извлечено из очереди рабочим процессом, и процесс удаления возобновится с шага 4. Более подробно обработка очередей рассматривается в документации Windows Azure Queue.
В данной лекции мы ознакомились с одной из абстракций данных Windows Azure Storage - Windows Azure Table. Это технология, которая обеспечивает структурированное хранилище состояний сервиса.
Windows Azure Table – абстракция данных, которая обеспечивает структурированное хранилище состояний сервиса.
Windows Azure Blob – абстракция данных, которая обеспечивает хранилище больших элементов данных.
Windows Azure Queue – абстракция данных, которая обеспечивает диспетчеризацию асинхронных заданий для реализации обмена данными между сервисами
Цель данной лекции – получить представление об архитектуре Windows Azure
Платформа Windows Azure – это модель Платформа как Сервис, которая предполагает запуск приложений на серверах и связанной сетевой инфраструктуре, размещенной в центрах обработки данных Microsoft и имеющей доступ в Интернет. Платформа состоит из мастшабируемой "облачной" операционной системы, фабрики хранения данных и связанных сервисов доставки через физические или логические (виртуализация) экземпляры Windows Server 2008. Комплект средств разработки Windows Azure (SDK) обеспечивает разработку версии "облачных сервисов", также хорошо, как инструменты и интерфейсы прикладного программирования (API), необходимые для разработки, разворачивания и управления масштабируемых сервисов в Windows Azure, включая шаблоны приложений Azure для Visual Studio 2008 и 2010. На рисунке 6.1 изображены компоненты основа "облачной" платформы и компоненты разработчика.
Согласно Microsoft, при использовании Azure Вы получаете:
(рис 6.1) Компоненты платформы Windows Azure и Комплекта средств разработки
Экономическая обстановка Microsoft во время выпуска платформы Azure акцентировала внимание на снижении затрат, что является основным поводом для использования Azure мелкими, средними и крупными ИТ отделами.
Microsoft разработали платформу Azure, позволив .NET разработчикам усилить их опыт создания в Visual Studio 2008 (и выше) ASP.NET веб приложений и Windows Communication Framework (WCF) сервисов. Проекты веб приложений запускаются в изолированной версии Internet Information Services (IIS) 7. Веб приложения и веб сервисы запускаются в частично доверенном механизме защиты, позволяющем ограничивать доступ коду к ресурсам компьютера (Code Access Security), который приблизительно соответсвует среднему уровню доверия ASP.NET и ограничивает доступ к некоторым ресурсам операционной системы. Комплект средств разработки Windows Azure (Март 2009) позволяет использоваться полный доступ к ресурсам компьютера для запуска не .NET кода, использования .NET библиотек, которые требуют полного доверия и процесс обработки взаимодействия, используя программные каналы (Pipe). Microsoft обещает поддержку запуска программного кода Ruby, PHP и Python в "облачной" платформе. Исходный вариант платформы разработки был ограничен средой программирования Visual Studio 2008 и выше с планом на поддержку инструментов Eclipse. Платформа Windows Azure поддерживает веб стандарты и протоколы включая SOAP, HTTP, XML, Atom и AtomPub.
Исходной точкой входа для разработчиков Azure для размещения ASP.NET приложений в облако является портал Windows Azure по адресу https://windows.azure.com/Cloud/Provisioning/Default.aspx. Портал требует входа с использованием Windows Live ID. Предварительная версия Azure (Community Technical Previews ,
Windows Azure, которая включает:
SQL Azure Live службы, которые включают:
Live сервисы: существующие интерфейсы прикладного программирования не являются частью предварительной версии и не требуют токена. С начала 2009 года Windows Azure токен дает право на одну учетную запись Hosted Service, две учетные записи для Storage. Вы запрашиваете токены Azure через страницу Microsoft Connect, на которую можно попасть со страницы портала.
На рисунке 6.1 показана страница учетной записи, которая содержит ссылки на страницы настроек и управления SQL Azure, сервисами .NET и Live сервисами. Эта страница также позволяет вам получать Azure и Live Framework
Предварительная версия марта 2009 года включает геолокацию, которая позволяет владельцам учетных записей выбрать центры обработки данных для расположения
Вы можете вставить GUID полученные в сообщении от члена команды Azure в текстовое окно Resource Token ID и нажать Claim Token для добавление еще одной или больше точки входа для подходящего объекта или нескольких объектов в список.
Если вы хотите разрабатывать веб сайты с поддержкой Live Framework или Mesh (программный комплекс для синхронизации данных в кроссплатформенных средах разработанный компанией Microsoft) веб приложений, необходимо запросить токен Live Framework по email meshctpe@microsoft.com. После того, как вы получите Live Framework токен, вы можете скачать и установить текущие версии Live Framework SDK и Live Framework Tools для Visual Studio по ссылкам указанным на странице http://dev.live.com/liveframework/sdk/. Вы должны оплатить Live Framework токен для того, чтобы скачать Live SDK и дополнительные инструменты. Нет необходимости использовать учетную запись Windows Azure для тестирования Azure
Хранилище Windows Azure Storage обеспечивает разработчикам возможность хранения данных в облаке. Приложение может выполнять доступ к своим данным в любой момент времени из любой точки планеты, хранить любой объем данных и как угодно долго. При этом данные гарантированно не будут повреждены и утеряны. Windows Azure Storage предлагает богатый набор абстракций данных:
Windows Azure Table - структурированное хранилище, которе поддерживает высокомасштабируемые таблицы в облаке, которые могут содержать миллиарды сущностей и терабайты данных. По мере увеличения трафика, система будет эффективно масштабироваться, автоматически подключая тысячи серверов. Структурированное хранилище реализовано в виде таблиц (Tables), в которых располагаются сущности (Entities), содержащие ряд именованных свойств (Properties). Вот некоторые из основных характеристик Windows Azure Table:
Рассмотрим модель данных таблицы Windows Azure Table:
<имяУчетнойЗаписи>.table.core.windows.net.Таблица имеет гибкую схему. Windows Azure Table отслеживает имя и типизированное значение каждого свойства каждой сущности. Приложение может моделировать фиксированную схему на стороне клиента, обеспечивая одинаковый набор свойств для всех создаваемых сущностей.
Рассмотрим некоторые дополнительные сведения о сущностях:
| Тип свойства | Описание |
|---|---|
| Binary | Массив байтов размером до 64 КБ. |
| Bool | Булево значение. |
| DateTime | 64-разрядное значение, представляющее время в формате UTC. Поддерживаемый диапазон значений: от 1/1/1600 до 12/31/9999. |
| Double | 64-разрядное значение с плавающей точкой. |
| GUID | 128-разрядный глобально уникальный идентификатор. |
| Int | 32-разрядное целое значение. |
| Int64 | 64-разрядное целое значение. |
| String | 16-разрядное UTF-кодированное значение. Размер строковых значений может быть до 64 КБ. |
Windows Azure Table обеспечивает возможность масштабирования таблиц до тысяч узлов хранения через распределение сущностей в таблице. При распределении сущностей желательно обеспечить, чтобы сущности, входящие в одно множество, располагались в одном узле хранения. Приложение формирует эти множества соответственно значениям свойства PartitionKey сущностей.
Приложениям должна быть известна рабочая нагрузка каждой отдельно взятой секции. Для обеспечения желаемых результатов тестирование должно моделировать максимальную рабочую нагрузку.
(рис 6.2) Примеры секций
На рисунке выше представлена таблица, содержащая множество версий документов. Каждая сущность данной таблицы соответствует определенной версии определенного документа. В этом примере ключом
Хорошая масштабируемость системы хранения достигается за счет распределения секций по множеству узлов хранения.
Система отслеживает характер использования секций и автоматически равномерно распределяет эти секции по всем узлам хранения. Это позволяет системе и приложению масштабироваться соответственно количеству запросов к таблице. То есть если некоторые секции запрашиваются больше других, система автоматически разнесет их на несколько узлов хранения, таким образом, распределяя трафик между множеством серверов. Однако секция, т.е. все сущности, имеющие одинаковый ключ секции, будут обслуживаться как один узел. Но даже несмотря на это, объем данных в рамках секции не ограничен емкостью хранилища одного узла хранения.
Сущности одной секции хранятся вместе. Это обеспечивает наиболее эффективную обработку запросов к секции. Более того, в этом случае приложение может использовать все преимущества эффективного кэширования и других оптимизаций производительности, обеспечиваемых расположением данных в секции.
В примере выше секцию образуют все версии одного документа. Таким образом, для извлечения всех версий данного документа необходимо выполнить доступ всего к одной секции. Чтобы получить все версии документов, измененные до 5/30/2007, придется запрашивать несколько секций, что будет не так эффективно и более ресурсоемко, поскольку по запросу должны будут проверяться все секции, которые к тому же могут располагаться на разных узлах хранения.
Выбор ключа секции важен с точки зрения обеспечения эффективного масштабирования приложения. При этом необходимо найти компромисс между размещением сущностей в одной секции, что обеспечивает большую эффективность запросов, и масштабируемостью таблицы, поскольку, чем больше секций в таблице, тем проще для Windows Azure Table распределить нагрузку между множеством серверов.
Для наиболее частых и критичных по времени ожидания запросов PartitionKey должен быть включен как часть выражения запроса. Запрос, в котором указан PartitionKey, будет намного эффективнее, поскольку в этом случае просматриваются сущности только одной секции. Если при выполнении запроса PartitionKey не указан, в поисках необходимых сущностей просматриваются все
Далее представлены некоторые советы и рекомендации по выбору PartitionKey для таблицы:
Теперь, когда приложение имеет набор
MSDN, мы обсудим, как оптимизировать использование Windows Azure Table и предотвратить возникновение таких ошибок в вашем приложении.
Также можно проанализировать расширяемость выбранных ключей, особенно если на момент их выбора нет точных сведений о характеристиках пользовательского трафика. В этом случае важно выбирать ключи, которые можно легко расширять для обеспечения более тонкого секционирования. Далее в данном документе приводится подробный пример этого.
Для таблиц и сущностей поддерживаются следующие базовые операции:
Для работы с таблицами в .NET-приложении можно просто использовать ADO.NET Data Services.
В следующей таблице приведен список предлагаемых API. Поскольку применение ADO.NET Data Services в итоге сводится к передаче REST-пакетов, приложения могут использовать REST напрямую. Кроме того, что REST обеспечивает возможность доступа к хранилищу посредством не-.NET языков, он также позволяет реализовывать более тонкое управление сериализацией/десериализацией сущностей, что пригодится при работе с такими сценариями, как наличие разных типов сущностей или более чем 255 свойств в таблице и т.д.
В приведенных ниже примерах описываются операции с таблицей "Blogs". В этой таблице хранятся блоги для приложения MicroBlogging.
В приложении MicroBlogging есть две таблицы: Channels (Каналы) и Blogs (Блоги). Имеется список каналов, блоги публикуются в определенном канале. Пользователи подписываются на каналы и ежедневно получают новые блоги этих каналов.
В данном примере рассмотрим только таблицу Blogs и приведем примеры следующих операций с ней:
Схема таблицы описывается как C#-класс. Такую модель использует ADO.NET Data Services. Схема известна только клиентскому приложению и упрощает доступ к данным. Сервер схему не применяет.
Рассмотрим описание сущностей Blog, хранящихся в таблице Blogs. Каждая сущность блога содержит следующие данные:
Во-первых, обратите внимание, что для таблицы определен PartitionKey, представляющий имя канала, частью которого является блог, и в качестве RowKey используется дата размещения блога. PartitionKey и RowKey – ключи таблицы Blogs, они объявляются посредством атрибута класса DataServiceKey (Ключ сервиса данных). То есть таблица Blogs секционирована по именам каналов (ChannelName). Это позволяет приложению эффективно извлекать самые недавние блоги канала, на который подписан пользователь. Кроме ключей, в качестве свойств объявлены характерные для пользователя атрибуты. Все свойства имеют открытые (public) методы считывания и присвоения значения и хранятся в таблице Windows Azure Table. Итак, в примере ниже:
[DataServiceKey("PartitionKey", "RowKey")]
public class Blog
{
// ChannelName
public string PartitionKey { get; set; }
// PostedDate
public string RowKey { get; set; }
// Определяемые пользователем свойства
public string Text { get; set; }
public int Rating { get; set; }
public string RatingAsString { get; }
protected string Id { get; set; }
}
Далее рассмотрим, как создать таблицу Blogs для учетной записи хранилища. Создание таблицы аналогично созданию сущности в основной таблице "Tables". Эта основная таблица определена для каждой учетной записи хранилища, и имя каждой таблицы, используемой учетной записью хранения, должно быть зарегистрировано в основной таблице. Описание класса основной таблицы приведено ниже, где свойство TableName (Имя таблицы) представляет имя создаваемой таблицы.
[DataServiceKey("TableName")]
public class TableStorageTable
{
public string TableName { get; set; }
}
Фактическое создание таблицы происходит следующим образом:
// Uri сервиса: "http://<Account>.table.core.windows.net/"
DataServiceContext context = new DataServiceContext(serviceUri);
TableStorageTable table = new TableStorageTable("Blogs");
// Создаем новую таблицу, добавляя новую сущность
// в основную таблицу "Tables"
context.AddObject("Tables", table);
// результатом вызова SaveChanges является отклик сервера
DataServiceResponse response = context.SaveChanges();
serviceUri – это uri сервиса таблицы, http://<Здесь указывается имя учетной записи>.table.core.windows.net/. DataServiceContext (Контекст сервиса данных) – один из основных классов сервиса данных ADO.NET, представляющий контекст времени выполнения для сервиса. Он обеспечивает API для вставки, обновления, удаления и запроса сущностей с помощью либо LINQ, либо RESTful URI и сохраняет состояние на стороне клиента.
Рассмотрим вставку элемента Blog. Чтобы вставить сущность, приложение должно выполнить следующее.
DataServiceContext, который представляет подключение к серверу в сервисе данных ADO .NET для вашей учетной записи хранилища.SaveChanges (Сохранить изменения) объекта DataServiceContext для отправки запроса серверу. Это обеспечивает отправку на сервер HTTP-запроса с сущностью в XML-формате ATOM.Далее представлены примеры кода для перечисленных выше операций:
Blog blog = new Blog {
PartitionKey = "Channel9", // ChannelName
RowKey = DateTime.UtcNow.ToString(), // PostedDate
Text = "Hello",
Rating = 3
};
serviceUri = new Uri("http://<account>.table.core.windows.net");
var context = new DataServiceContext(serviceUri);
context.AddObject("Blogs", blog);
DataServiceContext response = context.SaveChanges();
Запрос сущностей выполняется с помощью встроенного в C# языка запросов LINQ (Language Integrated Query). В данном примере извлечем все блоги, рейтинг которых равен 3.
При обработке запроса (например, с помощью выражение foreach), он передается на сервер. Сервер отправляет результаты в XML-формате ATOM. Клиентская библиотека ADO .NET Data Services десериализует результаты в C#-объекты, после чего они могут использоваться приложением.
var serviceUri = new Uri("http://<account>.table.core.windows.net");
DataServiceContext context = new DataServiceContext(serviceUri);
// LINQ-запрос с использованием DataServiceContext для выбора
// из таблицы Blogs всех сущностей блогов, для которых rating = 3
var blogs =
from blog in context.CreateQuery<blog>("Blogs")
where blogs.Rating == 3
select blog;
// запрос отправляется на сервер и выполняется
foreach (Blog blog in blogs) { }
Обновление сущности выполняется следующим образом.
DataContext (Контекст данных), свойству MergeOption (Вариант объединения) которого задается значение OverwriteChanges (Перезапись изменений) или PreserveChanges (Сохранение изменений), как описывается в разделе 4.8. Это обеспечивает правильную обработку ETag для каждого извлекаемого объекта.LINQ DataContext получает сущность, которая будет обновляться. Извлечение ее с сервера гарантирует обновление ETag в сущностях, отслеживаемых контекстом, и то, что при последующих обновлениях и удалениях в заголовке if-match будет использоваться обновленный ETag. Меняем C#-объект, представляющий сущность.DataContext для обновления. Использование того же DataContext гарантирует автоматическое повторное использование ETag, полученного ранее для этого объекта.SaveChanges для отправки запроса на сервер.Blog blog =
(from blog in context.CreateQuery<blog>("Blogs")
where blog.PartitionKey == "Channel9"
blog.RowKey == "Oct-29"
select blog).FirstOrDefault();
blog.Text = "Hi there";
context.UpdateObject(blog);
DataServiceResponse response = context.SaveChanges();
4.7 Удаление Blog
Удаление сущности аналогично ее обновлению. Для этого извлекаем сущность с помощью DataServiceContext и вызываем для содержимого вместо метода UpdateObject метод DeleteObject (Удалить объект).
// Получаем объект Blog для ("Channel9", "Oct-29")
context.DeleteObject(blog);
DataServiceResponse response = context.SaveChanges();
Рассмотрим рекомендации по работе с DataServiceContext:
DataServiceContext не обеспечивает безопасность потоков, поэтому он не может использоваться совместно разными потоками, а также имеет непродолжительное время существования.DataServiceContext не является объектом с длительным временем жизни. Вместо того, чтобы использовать один DataServiceContext в течение всей жизни потока, рекомендуется создавать объект DataServiceContext каждый раз, когда возникает необходимость выполнить ряд транзакций с WindowsAzureTable, и затем удалять этот объект.DataServiceContext и возникает сбой при выполнении SaveChanges, сведения об операции, давшей сбой, сохраняются в DataServiceContext. При последующем вызове SaveChanges попытка выполнить эту операцию повторяется.DataServiceContext имеет свойство MergeOption, которое используется для управления тем, как DataServiceContext обрабатывает отслеживаемые сущности. Возможные значения:AppendOnly (Только добавление): Это значение по умолчанию, при использовании которого DataServiceContext не загружает экземпляр сущности с сервера, если он уже имеется в его кэше.OverwriteChanges: DataServiceContext всегда загружает экземпляр сущности с сервера и перезаписывает предыдущий вариант сущности, т.е. обеспечивает соответствие экземпляра сущности ее текущему состоянию.PreserveChanges: Если экземпляр сущности существует в DataServiceContext, он не загружается из постоянного хранилища. Все изменения, вносимые в свойства объектов в DataServiceContext, сохраняются, но ETag обновляется, поэтому данную опцию следует использовать при необходимости восстановления после ошибок совместного доступа с нежесткой блокировкой.NoTracking (Без отслеживания): DataServiceContext не отслеживает экземпляры сущностей. Обновление сущности
в контексте без отслеживания реализуется с помощью Etag, который обновляется посредством AttachTo. Этот вариант
не рекомендуется к применению.context.AttachTo("Blogs", blog, "etag to use");
context.UpdateObject(blog);
context.SaveChanges();
Когда MergeOption контекста задано значение AppendOnly и объект DataServiceContext уже отслеживает сущность в результате предыдущей операции извлечения или добавления, повторное извлечение сущности с сервера не приведет к обновлению отслеживаемой сущности в контексте. Таким образом, если сущность на сервере была изменена, последующие обновления/удаления приведут к сбою необходимых условий ( PreCondition ). В примере кода раздела 5 MergeOption задано значение PreserveChanges, которое обеспечивает, что сущность будет загружаться с сервера всегда.
Результатом всех рассматриваемых выше операций является передача HTTP-сообщений на и с сервера. Приложение может отказаться от использования клиентской библиотеки .NET и работать на уровне HTTP/REST.
Рассмотрим параллельные обновления. Для обновления сущности необходимо выполнить следующие операции.
Предположим, два процесса, выполняющихся параллельно, пытаются обновить одну и ту же сущность. Поскольку шаги 1 и 2 не являются неделимыми, на любом из них может возникнуть ситуация внесения изменений в уже устаревшую версию сущности. Для решения этой проблемы Windows Azure Table использует нежесткую блокировку.
ETag HTTP.UPDATE (обновить) на сервер, он отправляет на него этот ETag в виде заголовка If-Match.ETag в заголовке If-Match, изменение принимается, и хранящаяся на сервере сущность получает новую версию. Эта новая версия возвращается клиенту как заголовок ETag.ETag в заголовке If-Match, изменение отклоняется, и клиенту
возвращается HTTP-ошибка "precondition failed" (необходимое условие не выполнено).При получении ошибки "precondition failed" типовым поведением клиентского приложения будет повторение всей операции, как показано в фрагменте кода ниже.
При использовании клиентской библиотеки .NET приложение получает HTTP-код ошибки в виде исключения DataServiceRequestException.
В примере ниже два разных клиента выполняют один и тот же код для изменения текста. Эти два клиента пытаются задать Text разные значения.
ETag, например, "v1". Оба клиента полагают, что предыдущая версия сущности – "v1".Text.UpdateObject и SaveChanges."If-Match: v1".If-Match с версией сущности. Они совпадают."v2"."ETag:v2".If-Match с версией сущности. Они не совпадают, поскольку версия сущности уже изменена на "v2", тогда как в запросе указывается версия "v1".// Задаем такой вариант объединения, который обеспечивает
// сохранение обновлений, но позволяет обновление etag.
// По умолчанию применяется значение AppendOnly, при котором
// уже отслеживаемая сущность не перезаписывается значениями,
// полученными с сервера, в результате чего в случае изменения
// сущности на сервере используется недействительный etag.
context.MergeOption = MergeOption.PreserveChanges;
Blog blog =
(from blog in context.CreateQuery<blog>(quot;Blogsquot;)
where blog.PartitionKey == quot;Channel9quot;
blog.RowKey == quot;Oct-29quot;
select blog).FirstOrDefault();
blog.Text = quot;Hi there againquot;;
try
{
context.UpdateObject(blog);
DataServiceResponse response = context.SaveChanges();
}
catch (DataServiceRequestException e)
{
OperationResponse response = e.Response.First();
if (response.StatusCode == (int)HttpStatusCode.PreconditionFailed)
{
// выполняем запрос объекта повторно, чтобы получить
// последний etag, и проводим обновление
}
}
Для безусловного обновления сущности приложение выполняет следующее:
DataServiceContext или, в случае использования существующего контекста, отсоединяет объект, как демонстрирует пример ниже."*" как новое значение ETag.SaveChanges.// задаем опцию объединения, разрешающую перезапись,
// чтобы обеспечить возможность обновления отслеживаемой сущности
context.Detach(blog);
// Присоединяем сущность к контексту, используя имя таблицы, сущность,
// которая должна быть обновлена, и "*" как значение etag.
context.AttachTo("Blogs", blog, "*");
blog.Text = "Hi there again";
try
{
context.UpdateObject(blog);
DataServiceResponse response = context.SaveChanges();
}
catch (DataServiceRequestException e)
{
// Обработка ошибки, но в данном случае формировнание ошибки PreCondition невозможно
}
Для запросов, которые могут возвращать большое количество результатов, система обеспечивает два механизма:
Take(N).Система поддерживает функцию возвращения первых N соответствующих запросу сущностей. Например, если программа разрабатывается на .NET, для извлечения первых N сущностей (в данном примере это первые 100 сущностей) можно использовать LINQ-функцию Take(N).
serviceUri = new Uri("http://<account>.table.core.windows.net");
DataServiceContext svc = new DataServiceContext(serviceUri);
var allBlogs = context.CreateQuery<blog>("Blogs");
foreach (Blog blog in allBlogs.Take(100))
{
// выполняем некоторые операции с каждым блогом
}
Аналогичная функциональность поддерживается в интерфейсе REST через опцию строки запроса $top=N. Например, запрос "GET http://<UriСервиса>/Blogs?$top=100" обеспечил бы возвращение первых 100 сущностей, соответствующих запросу. Фильтрация выполняется на сервере, поэтому в ответе клиенту может быть передано максимум 100 сущностей.
REST ).В любом из этих случаев ответ будет включать маркер продолжения в виде специального заголовка. Для запроса к вашим сущностям используются такие заголовки:
x-ms-continuation-NextPartitionKeyx-ms-continuation-NextRowKeyЕсли клиент получил эти значения, он должен передать их со следующим запросом в виде опций HTTP-запроса; во всем остальном запрос остается неизменным. Это обеспечит возвращение следующего набора сущностей, начинающегося с места, обозначенного маркером продолжения.
Последующий запрос выглядит следующим образом:
http://<UriСервиса>/Blogs?<исходныйЗапрос>NextPartitonKey=<некотороеЗначение>NextRowKey=<другоеЗначение>
Это повторяется до тех пор, пока клиентом не будет получен ответ без маркера продолжения, что свидетельствует об извлечении всех соответствующих запросу результатов.
Маркер продолжения должен рассматриваться как непрозрачное значение. Оно указывает на точку начала следующего запроса и может не соответствовать фактической сущности в таблице. Если в таблицу добавляется новая сущность, так что Key (новая сущность) > Key (последняя сущность, извлеченная запросом), но Key (новая сущность) < "Маркера продолжения", тогда эта новая сущность не будет возвращена повторным запросом, использующим маркер продолжения. Но новые сущности, добавленные так, что Key(новая сущность) > "Маркера продолжения", войдут в результаты, возвращаемые последующими использующими маркер продолжения запросами.
Теперь рассмотрим модель согласованности, обеспечиваемую Windows Azure Table.
В рамках одной таблицы система обеспечивает гарантии транзакции ACID для всех операций вставки/обновления/удаления для одной сущности.
Для запросов в рамках отдельной секции выполняется изоляция моментального снимка. Запрос обеспечивается согласованным представлением секции с момента его начала и в течение всей транзакции. Моментальный снимок обеспечивает следующее:
Изоляция моментального снимка поддерживается только в рамках секции и в рамках одного запроса. Система не поддерживает изоляцию моментального снимка для нескольких секций таблицы или других фаз запроса.
Приложения отвечают за сохранение согласованности между множеством таблиц.
В примере MicroBlogging использовалось две таблицы: Channels и Blogs. Приложение выполняет согласование таблиц Channels и Blogs. Например, когда канал удаляется из таблицы Channels, приложение должно удалить соответствующие блоги из таблицы Blogs.
Сбои могут возникать в моменты синхронизации состояния множества таблиц. Приложение должно уметь обрабатывать такие сбои и иметь возможность возобновлять работу с момента, на котором она была прервана.
В предыдущем примере, когда канал удаляется из таблицы каналов, приложение должно также удалить все блоги этого канала из таблицы Blogs. В ходе этого процесса могут возникать сбои приложения. Для обработки таких сбоев приложение может сохранять транзакцию в Windows Azure Queues, что позволяет пользователю возобновить операцию удаления канала и всех его блогов даже в случае сбоя.
Вернемся к примеру с таблицами Channels и Blogs. Channels имеет следующие свойства: Name (Имя) как PartitionKey, пустая строка как RowKey, Owner (Владелец), CreatedOn (Дата создания). И Blogs имеет свойства Channel Name (Имя канала) как PartitionKey, CreatedOn как RowKey, Title (Название), Blog, UserId. Теперь, когда канал удален, необходимо обеспечить, чтобы все ассоциированные с ним блоги также были удалены. Для этого выполняем следующие шаги:
"DeleteChannelAndBlogs" (Удаление каналов и блогов)."DeleteChannelAndBlogs".DeleteChannelAndBlogs, задавая для извлеченного элемента очереди время невидимости
в течение N секунд. При этом элемент, определяющий имя канала, который должен быть удален, изымается. Если роль работника удаляет элемент очереди
в течение этих N секунд, данный элемент будет удален из очереди. Если нет, элемент станет вновь видимым и доступным для использования рабочей ролью.
При извлечении элемента рабочая роль делает следующее:Channels помечает канал как недействительный, чтобы с этого момента никто не мог выполнять чтение из него.Blogs все записи, для которых PartitionKey = "имени канала", указанному в элементе очереди.Channels.Если в ходе выполнения, например, шага 4, возникает какой-либо сбой, производится аварийное завершение рабочего процесса, при этом элемент очереди не удаляется из нее. Таким образом, как только соответствующий элемент очереди станет снова видимым (т.е. когда истечет время, заданное как время ожидания видимости), это сообщение будет вновь извлечено из очереди рабочим процессом, и процесс удаления возобновится с шага 4. Более подробно обработка очередей рассматривается в документации Windows Azure Queue.
В данной лекции мы ознакомились с одной из абстракций данных Windows Azure Storage - Windows Azure Table. Это технология, которая обеспечивает структурированное хранилище состояний сервиса.
Windows Azure Table – абстракция данных, которая обеспечивает структурированное хранилище состояний сервиса.
Windows Azure Blob – абстракция данных, которая обеспечивает хранилище больших элементов данных.
Windows Azure Queue – абстракция данных, которая обеспечивает диспетчеризацию асинхронных заданий для реализации обмена данными между сервисами
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.