Алексей Шуленин эксперт по технологиям обработки и анализа информации департамент стратегических технологий Российское представительство Microsoft Microsoft.

Презентация:



Advertisements
Похожие презентации
Microsoft TechDays Павел Маслов MVP, Directory Services.
Advertisements

Microsoft TechDays Богомолов Алексей MCP
Microsoft TechDays Николай Миляев консультант Microsoft.
Microsoft TechDays Золотовицкий Аркадий Директор по производству «Интеллектуальные системы»
Microsoft TechDays Виталий Дильмухаметов
Microsoft TechDayshttp:// Коршиков Андрей Фёдорович ведущий инженер-программист ЗАО «НИПИ «ИнжГео» MCT, MCITP, MCPD.
Microsoft TechDays Марат Бакиров Эксперт по разработке ПО Microsoft
Microsoft TechDays Константин Трещев MCITP: Enterprise Administrator
Microsoft TechDays Александр Неволин Nevlabs кандидат технических наук.
Microsoft TechDays Леонид Шапиро MCT ЦКО «Специалист»
Microsoft TechDays Ксения Хмелёва Специалист по технологиям Microsoft.
Microsoft TechDays Людмила Шайкина Quarta Consulting
Microsoft TechDays Тучков Вячеслав
Ромуальд Здебский Microsoft.
Msdevcon.ru#msdevcon. OPEN SOURCE РЕШЕНИЯ В ОБЛАКЕ WINDOWS AZURE Воркачёв Владимир.
Microsoft TechDays Дмитрий Рудых.
Электронная Библиотека Президента Полнотекстовый поиск на базе iFTS SQL Server Июнь 2009| MSC.
Microsoft TechDays Никоноров Евгений разработчик EPAM Systems.
Новые продукты Microsoft для повышения качества и эффективности образования Амит Миталь Старший вице-президент Microsoft по развитию социальных проектов.
Microsoft TechDays Евгений Марченков Эксперт по технологиям разработки ПО Microsoft.
Транксрипт:

Алексей Шуленин эксперт по технологиям обработки и анализа информации департамент стратегических технологий Российское представительство Microsoft Microsoft Corporation

АбстракцияСеть Динамические библиотеки Статические библиотеки Идея Идея повторного использования кода Процедуры (подпрограммы) DLL/СборкиRPCобъектыКомпоненты DCOM/.net REMOTING Сервисы

Не требует крупных предварительных инвестиций В случае неудачи проекта не нужно ломать голову, куда пристроить дорогостоящее оборудование В случае удачи автоматически решается проблема масштабирования со 100 пользователей на 1000, на 10000,... Меньше операционных издержек Размещение громадных количеств пользователей на высокомасштабируемом сервере дает стоимость в расчете на пользователя на порядки меньше, чем в случае развертывания системы на предприятии Пересекает границы организации Файрвол не преграда Ценность информации многократно возрастает, если расширить ее на партнеров, поставщиков, клиентов Проще, чем строить экстранет Быстрая подготовка к работе Пользователям не требуется ждать внедрения и настройки специализированных средств Позволяет IT сфокусироваться на инновациях

Multitenancy hosted model Несколько организаций шарят одну базу Грубо говоря, каждый эккаунт привязан к своей схеме Стандартный доступ через SOAP, REST, XML, ODBC, JDBC, SQL Можно создавать таблички, DRI, запрашивать, добавлять, изменять данные Нет задачи сопровождать и поддерживать Dedicated database hosted model Каждой организации выделяется по БД Все БД шарят общую инфраструктуру: сервера, сторидж,... Доступ по стандартным протоколам, что и в пред.случае DBA клиента может апгрейдить, тюнить базу, вообще делать с ней, что хочет – она же его выделенная Database container model Обращаемся уже не к таблицам, а к сущностям Более высокий уровень абстракции Сущности, вообще говоря, нереляционны, хотя основываются на реляционных таблицах Базовая сущность – набор свойств со значениями, сущности могут наследовать друг от друга Доступ к контейнеру сущностей как к веб-сервису (REST, SOAP)

Транспорт и инфраструктура сервисов Windows Communication Foundation Масштабируемый хостинг сервисов и приложений Windows Azure Связь разнородных сервисов между собой.NET Services Авторизация LiveID, CardSpace (Client),.Net Services Масштабируемая свободно структурированная база данных, доступная по REST и SOAP SQL Services Структурированная база данных в виде REST ADO.NET Data Services Синхронизация данных ADO.NET Synchronization Services, Sync Framework, Live Framework

Миллионы геораспределенных машин, распределяемая по географическому принципу доставка информации петабайты данных, петафлопы вычислительной мощности Масштабируемость Недорогие процессоры, диски IDE/SATA Уменьшение капиталозатрат Самомониторинг, самонастройка, самоизлечение Уменьшение операционных издержек На которое не оказывают влияния программные, аппаратные и коммуникационные сбои Предсказуемое детерминированное последовательное поведение Инновационные алгоритмы Высокая производительность

Windows Azure SDK - примеры Windows Azure Tools for Microsoft Visual Studio - шаблоны проектов Подробнее - см., напр.,

Состав SDS Explorer - графическая утилита для управления authorities / контейнерами / сущностями Утилита командной строки SDS Command Prompt Размер КБ Ставится отсюда: A5C6-EC9D-440B-939E-481DD05F2627&displaylang=en

Создание Authority

Просмотр набора имеющихся у эккаунта authorities:

Получение сущности Metadata Properties (служебные поля) Kind Id Version Flexible Properties (пользовательские поля) Flexible Properties (пользовательские поля)

Разные наборы свойств в разных сущностях Разные типы данных у свойств с одинаковым именем Каждая сущность создается отдельно 1 Руслан и Людмила ж1 2 Борис Годунов ж Герой нашего времени ж Введение в SDS ж Руслан и Людмила ж1 2 Борис Годунов ж Герой нашего времени ж Введение в SDS ж2 10

LINQ-подобный язык запросов Подробнее - см. BOL на SDS ( us/library/cc aspx) us/library/cc aspx Пример (from жанр in entities.OfKind("Жанр") where жанр["Жанр"] == "Классика" from книга in entities.OfKind("Книга") where книга["Жанр"] == жанр.Id orderby книга["Название"] select книга).Take(2) Комментарии Обращение к служебным св-вам: книга.Id, к пользовательским - книга["Жанр"] Case sensitive: книга["жанр"] не поймет В то же время и ошибки не будет - схема-то гибкая entities.OfKind("Жанр") то же, что where жанр.Kind == "Жанр": && … Результат метода OfKind() сам является selectом (как и entities) Можно просто написать в качестве запроса entities.OfKind(...). Можно использовать «статическое звучание» метода Вместо (select...).Take(n) - Take(select..., n)

HTTP-методы POST, GET, PUT, DELETE преобразуются в CRUD Иными словами, в INSERT / SELECT / UPDATE / DELETE На самом деле мы ее все это время наблюдали SDS Explorer – это приложение, работающее с SDS по REST Имеется полезная кнопка Request-Response, которая позволяет посмотреть, что уходит/приходит по HTTP во время выполнения действий над объектами SDS Существенно облегчает создание собственного REST-приложения

Все, что требуется – сформировать соответствующий HTTP Request и отправить его на URL SDS. C:\Events\"09-02 TechDays"\SDS\REST\SDS_GetSitkaPwd.ps1 [string] $login = "alexejs"; [string] $password = GetSitkaPwd function GetWebPage([string] $url) { [net.httpWebRequest] $req = [net.webRequest]::create($url) $req.Credentials = new-object Net.NetworkCredential($login, $password) [net.httpWebResponse] $rep = $req.getResponse() [IO.StreamReader]$sr = new-object IO.StreamReader($rep.getResponseStream()) return $sr.ReadToEnd() } [string] $url = " [string] $output = GetWebPage($url) [console]::WriteLine(); [console]::WriteLine($output); [console]::WriteLine(). C:\Events\"09-02 TechDays"\SDS\REST\SDS_GetSitkaPwd.ps1 [string] $login = "alexejs"; [string] $password = GetSitkaPwd function GetWebPage([string] $url) { [net.httpWebRequest] $req = [net.webRequest]::create($url) $req.Credentials = new-object Net.NetworkCredential($login, $password) [net.httpWebResponse] $rep = $req.getResponse() [IO.StreamReader]$sr = new-object IO.StreamReader($rep.getResponseStream()) return $sr.ReadToEnd() } [string] $url = " [string] $output = GetWebPage($url) [console]::WriteLine(); [console]::WriteLine($output); [console]::WriteLine() Взято из Request на пред.слайде

Создание ссылки на Windows Communication Foundation-сервис SDS

Читается wsdl, создается прокси Становится доступной объектная модель IntelliSense

Выполнение запроса SitkaSoapSer viceClient.Qu ery(scope, «текст запроса») запрос

В отличие от REST, помимо базовой, поддерживаются: // Access Control Service proxy = new SitkaSoapServiceClient("UsernameTokenEndpoint"); proxy.ClientCredentials.UserName.UserName = "solutionname"; proxy.ClientCredentials.UserName.Password = "solutionpassword"; //CardSpace proxy = new SitkaSoapServiceClient("CardSpaceTokenEndpoint"); proxy.DisplayInitializationUI(); //вызывает CardSpace prompt proxy.Open(); //для CardSpace требуется явное открытие прокси //X.509 proxy = new SitkaSoapServiceClient("CertificateTokenEndpoint"); proxy.ClientCredentials.ClientCertificate.SetCertificate( "CN=localhost", StoreLocation.LocalMachine, StoreName.My ); //предварительно требуется создать сертификат (с закрытым ключом) и установить его куда-нибудь на данную машину (например, в Local Computer\Personal\Certificates), Personal Conainer – это StoreName.My). //Также создать самогенерящийся открытый ключ сертификата в Local Computer\Trusted People\Certificates, чтобы он валидировался Адрес службы

static void Main(string[] args) { SitkaSoapServiceClient proxy = new SitkaSoapServiceClient("BasicAuthEndpoint"); proxy.ClientCredentials.UserName.UserName = "alexejs"; proxy.ClientCredentials.UserName.Password = Settings.Default.SitkaPassword; Scope scope = new Scope(); scope.AuthorityId = "leshik"; scope.ContainerId = "Библиотека"; scope.EntityId = "1"; Entity entity = proxy.Get(scope); Debug.WriteLine("Старое значение версии = " + entity.Version); entity.Properties["Название"] = "Руслан и Людмила"; scope.VersionMatch = new VersionMatch(); scope.VersionMatch.Version = entity.Version; scope.VersionMatch.MatchType = VersionMatchType.Match; try { scope = proxy.Update(scope, entity); } catch (System.ServiceModel.FaultException e) { string errMsg; switch (e.Detail.StatusCode) { case ErrorCodes.EntityNotFound: errMsg = String.Format("Эвона! А сущность с Id {0} уже кто-то прихлопнул :(", entity.Id); break; case ErrorCodes.PreconditionFailed: errMsg = String.Format("Дык ить сущность с Id {0} с тех пор вроде как того, поменялась :(", entity.Id); break; default: errMsg = "Чета случилось, а че - хтож ево знаить :("; break; } Debug.WriteLine(errMsg); } Debug.WriteLine("Новое значение версии = " + scope.VersionMatch.Version); proxy.Close(); } static void Main(string[] args) { SitkaSoapServiceClient proxy = new SitkaSoapServiceClient("BasicAuthEndpoint"); proxy.ClientCredentials.UserName.UserName = "alexejs"; proxy.ClientCredentials.UserName.Password = Settings.Default.SitkaPassword; Scope scope = new Scope(); scope.AuthorityId = "leshik"; scope.ContainerId = "Библиотека"; scope.EntityId = "1"; Entity entity = proxy.Get(scope); Debug.WriteLine("Старое значение версии = " + entity.Version); entity.Properties["Название"] = "Руслан и Людмила"; scope.VersionMatch = new VersionMatch(); scope.VersionMatch.Version = entity.Version; scope.VersionMatch.MatchType = VersionMatchType.Match; try { scope = proxy.Update(scope, entity); } catch (System.ServiceModel.FaultException e) { string errMsg; switch (e.Detail.StatusCode) { case ErrorCodes.EntityNotFound: errMsg = String.Format("Эвона! А сущность с Id {0} уже кто-то прихлопнул :(", entity.Id); break; case ErrorCodes.PreconditionFailed: errMsg = String.Format("Дык ить сущность с Id {0} с тех пор вроде как того, поменялась :(", entity.Id); break; default: errMsg = "Чета случилось, а че - хтож ево знаить :("; break; } Debug.WriteLine(errMsg); } Debug.WriteLine("Новое значение версии = " + scope.VersionMatch.Version); proxy.Close(); }

static void Main(string[] args) { string login = "alexejs", password = Settings.Default.SitkaPassword; string authorityId = "leshik", containerId = "Библиотека", entityId = "1"; string url = " + authorityId + ".data.database.windows.net/v1/" + containerId + "/" + entityId; XmlDocument entityXml = new XmlDocument(); HttpWebRequest req = (HttpWebRequest) WebRequest.Create(url); req.Credentials = new NetworkCredential(login, password); req.ContentType = "application/x-ssds+xml"; //Читаем сущность c Id = entityId в entityXml (XmlDocument). req.Method = "GET"; HttpWebResponse rep = (HttpWebResponse) req.GetResponse(); string xml_сущности_в_виде_текста = new StreamReader(rep.GetResponseStream()).ReadToEnd(); entityXml.LoadXml(xml_сущности_в_виде_текста); rep.Close(); Debug.WriteLine("\nУспешно прочитана сущность:\n" + xml_сущности_в_виде_текста); //Из XML вытаскиваем и запоминаем версию XmlNamespaceManager nsmgr = new XmlNamespaceManager(entityXml.NameTable); nsmgr.AddNamespace("s", " XmlNode x = entityXml.DocumentElement.SelectSingleNode("s:Version", nsmgr); string версия = x.InnerText; //Меняем какие-нибудь св-ва сущности entityXml.SelectSingleNode("Книга/Название").InnerText = "Руслан и Людмила"; xml_сущности_в_виде_текста = entityXml.InnerXml; Debug.WriteLine("Изменяем сущность к виду:\n" + xml_сущности_в_виде_текста);... static void Main(string[] args) { string login = "alexejs", password = Settings.Default.SitkaPassword; string authorityId = "leshik", containerId = "Библиотека", entityId = "1"; string url = " + authorityId + ".data.database.windows.net/v1/" + containerId + "/" + entityId; XmlDocument entityXml = new XmlDocument(); HttpWebRequest req = (HttpWebRequest) WebRequest.Create(url); req.Credentials = new NetworkCredential(login, password); req.ContentType = "application/x-ssds+xml"; //Читаем сущность c Id = entityId в entityXml (XmlDocument). req.Method = "GET"; HttpWebResponse rep = (HttpWebResponse) req.GetResponse(); string xml_сущности_в_виде_текста = new StreamReader(rep.GetResponseStream()).ReadToEnd(); entityXml.LoadXml(xml_сущности_в_виде_текста); rep.Close(); Debug.WriteLine("\nУспешно прочитана сущность:\n" + xml_сущности_в_виде_текста); //Из XML вытаскиваем и запоминаем версию XmlNamespaceManager nsmgr = new XmlNamespaceManager(entityXml.NameTable); nsmgr.AddNamespace("s", " XmlNode x = entityXml.DocumentElement.SelectSingleNode("s:Version", nsmgr); string версия = x.InnerText; //Меняем какие-нибудь св-ва сущности entityXml.SelectSingleNode("Книга/Название").InnerText = "Руслан и Людмила"; xml_сущности_в_виде_текста = entityXml.InnerXml; Debug.WriteLine("Изменяем сущность к виду:\n" + xml_сущности_в_виде_текста);...

//Апдейтим сущность на сервер req = (HttpWebRequest)WebRequest.Create(url); req.Credentials = new NetworkCredential(login, password); req.ContentType = "application/x-ssds+xml"; req.Method = "PUT"; req.Headers["If-Match"] = версия; //если на сервере будет уже другая версия, выкинется исключение Encoding кодировка = Encoding.UTF8; req.ContentLength = кодировка.GetByteCount(xml_сущности_в_виде_текста); req.GetRequestStream().Write(кодировка.GetBytes(xml_сущности_в_виде_текста), 0, (int)req.ContentLength); try { rep = (HttpWebResponse)req.GetResponse(); Debug.WriteLine("Обновление прошло успешно. Новая версия записи = " + rep.Headers["eTag"]); rep.Close(); } catch (WebException e) { rep = (HttpWebResponse)e.Response; if (e.Status == WebExceptionStatus.ProtocolError) switch (rep.StatusCode) { case HttpStatusCode.NotFound: Debug.WriteLine(String.Format("Эвона! А сущность с Id {0} уже кто-то прихлопнул :(", entityId)); break; //rep.StatusDescription == "Not Found" //e.Message == "The remote server returned an error: (404) Not Found." case HttpStatusCode.PreconditionFailed: Debug.WriteLine(String.Format("Дык ить сущность с Id {0} с тех пор вроде как того, поменялась :(", entityId)); break; //rep.StatusDescription == "A precondition, such as Version, could not be met." //e.Message == {"The remote server returned an error: (412) A precondition, such as Version, could not be met." } else Debug.WriteLine("Чета случилось, а че - хтож яво таперича знаить :("); } Debug.WriteLine(""); } //Апдейтим сущность на сервер req = (HttpWebRequest)WebRequest.Create(url); req.Credentials = new NetworkCredential(login, password); req.ContentType = "application/x-ssds+xml"; req.Method = "PUT"; req.Headers["If-Match"] = версия; //если на сервере будет уже другая версия, выкинется исключение Encoding кодировка = Encoding.UTF8; req.ContentLength = кодировка.GetByteCount(xml_сущности_в_виде_текста); req.GetRequestStream().Write(кодировка.GetBytes(xml_сущности_в_виде_текста), 0, (int)req.ContentLength); try { rep = (HttpWebResponse)req.GetResponse(); Debug.WriteLine("Обновление прошло успешно. Новая версия записи = " + rep.Headers["eTag"]); rep.Close(); } catch (WebException e) { rep = (HttpWebResponse)e.Response; if (e.Status == WebExceptionStatus.ProtocolError) switch (rep.StatusCode) { case HttpStatusCode.NotFound: Debug.WriteLine(String.Format("Эвона! А сущность с Id {0} уже кто-то прихлопнул :(", entityId)); break; //rep.StatusDescription == "Not Found" //e.Message == "The remote server returned an error: (404) Not Found." case HttpStatusCode.PreconditionFailed: Debug.WriteLine(String.Format("Дык ить сущность с Id {0} с тех пор вроде как того, поменялась :(", entityId)); break; //rep.StatusDescription == "A precondition, such as Version, could not be met." //e.Message == {"The remote server returned an error: (412) A precondition, such as Version, could not be met." } else Debug.WriteLine("Чета случилось, а че - хтож яво таперича знаить :("); } Debug.WriteLine(""); }

Подготовить из таблицы XML с определениями сущностей Превращаем каждую запись в сущность Делается элементарным запросом SELECT … FOR XML Загрузить полученный XML с определениями сущностей на SDS Делается при помощи утилиты st.exe (вторая в составе SDK) Мне неизвестно о существовании у SDS специализированных интерфейсов массовой загрузки Поэтому я полагаю, что чуда не происходит Утилита разбивает пакетный XML на куски по числу заказанных потоков Чтобы на каждый поток пришлось примерно равное кол-во сущностей И создает их по заказанному протоколу аналогично рассмотренным выше способам

sqlcmd -S (local) -d Northwind -E -i c:\temp\CustomerQuery.sql -o Customers.xml

"%programfiles%"\"Microsoft SQL Data Services SDK"\st.exe loadbatch leshik Northwind c:\Temp\Customers.xml /rest /overwrite /verbose /parallel:4

На конференции MIX09 в марте было объявлено ( us/sqlserver/dataservices/default.aspx), что SDS будут поддерживать произвольный T-SQLный доступ по обычному протоколу TDShttp://msdn.microsoft.com/en- us/sqlserver/dataservices/default.aspx Таким образом, работа с SQL Server в Облаке не будет отличаться от работы с локальным SQL Server Это здорово, но означает, что только что расказанное уже не актуально До мая закрытое тестирование, май - июнь - по приглашениям, с июля - все желающие Модель ACE и доступ по REST/SOAP в настоящее время остаются, но впоследствии перейдут в Azure Storage

Evolves SDS Next TDS + TSQL Model Web App SQL Client * Windows Azure Browser Application Application REST Client REST (Astoria) ADO.Net + EF Application SQL Client * Cloud HTTP HTTP+REST TDS * Client access enabled using TDS for ODBC, ADO.Net, OLEDB, PHP-SQL, Ruby, … Data Center ODBC, OLEDB, ADO.Net PHP, Ruby, … SDS Current REST/SOAP + ACE Model Web App REST Client Windows Azure Browser Application Application REST Client HTTP HTTP+REST Data Center Cloud

Сочетание преимуществ привычной работы с SQL Server и неограниченной доступности и масштабируемости Облака ценой минимальных административных издержек Знакомая реляционная модель SQL Server Использование существующих инструментов и API Поддерживается работа из PHP, Ruby, Java Просто БД в Облаке

Каждый account объект биллинга владеет одним или несколькими виртуальными серверами Каждый server хостит одну или несколько БД, включая virtual master каждая БД ограничена в размерах На сервере заводятся logins Каждая database имеет много SQL users Server=server1.data.database.windows.net Database=testDB (отображается на testuser)

По-прежнему автоматическая репликация, избыточность, контроль здоровья и восстановление в случае сбоя Machine 5 SQL Instance SQL DB DB5 DB1 DB3 DB2 Provisioning (databases, accounts, roles…), Metering, and Billing Machine 6 SQL Instance SQL DB DB1 DB6 DB2 DB3 Machine 4 SQL Instance SQL DB DB1 DB2 DB3 DB4 Machine 7 SQL Instance SQL DB DB4 DB5 DB1 DB7 Scalability and Availability: Fabric, Failover, Replication, and Load Balancing

Symmetric Programming ModelData Hub Aggregation

© 2007 Microsoft Corporation. All rights reserved. Microsoft, Windows, Windows Vista and other product names are or may be registered trademarks and/or trademarks in the U.S. and/or other countries. The information herein is for informational purposes only and represents the current view of Microsoft Corporation as of the date of this presentation. Because Microsoft must respond to changing market conditions, it should not be interpreted to be a commitment on the part of Microsoft, and Microsoft cannot guarantee the accuracy of any information provided after the date of this presentation. MICROSOFT MAKES NO WARRANTIES, EXPRESS, IMPLIED OR STATUTORY, AS TO THE INFORMATION IN THIS PRESENTATION.