Как мы разрабатывали вэб приложение на Microsoft Azure

 

На сегодняшний день в сети Internet существует огромное количество веб-камер доступных для общего просмотра. Веб-камеры позволяют просматривать потоковое видео в реальном времени, или же получать отдельные текущие кадры по запросу. Но чего они не умеют – так это хранить видео за более менее долгий промежуток времени. Это и понятно, для сохранения видео или просто коллекции изображений нужны вычислительные ресурсы – дисковое пространство на сервере и процессорное время на обработку запросов к видео архиву. Вот эту функциональность мы и решили реализовать в нашем проекте Enterra WebCam Viewer.

Итак, Enterra WebCam Viewer – это веб-приложение, которое должно иметь следующую функциональность:

  • При входе в приложение пользователь должен видеть список общедоступных (public) камер, которые обрабатываются нашим приложением, т.е. для которых ведется видео архив;
  • При переходе на конкретную камеру пользователь должен иметь возможность просмотра видео (или отдельных снимков) за указанный временной период.

Описанная выше функциональность – это функциональность для пользователя с правами «гость». Но камеры сами собой не появятся в приложении, их должен кто-то добавить. Пусть их добавляют сами пользователи. Для этого мы предусматриваем функциональность для зарегистрированного в нашей системе пользователя:

  • Регистрация нового пользователя, простейшее управление учетной записью (смена пароля);
  • Управление камерами пользователя: создание камеры, удаление, редактирование.

Видео архив для камеры формируется из изображений, взятых с камеры с определенным интервалом. Так, например, обычное видео – это последовательность изображений с частотой 24-25 кадров в секунду. Полноценная видео запись с такой частотой требует очень больших затрат процессорного времени и дискового пространства. К тому же вряд ли есть практическая необходимость делать запись с такой частотой с веб-камер. Поэтому считаем, что пользователь должен иметь возможность выставления собственной частоты кадров, не чаще 1 кадра в секунду. Кроме этого пользователь должен иметь возможность останавливать запись камеры без ее удаления.

Системные требования

Из описания функциональности сразу следует вывод о том, что нам потребуется серьезные вычислительные ресурсы. Во-первых, камеры надо постоянно обрабатывать, надо с них брать изображения и куда то сохранять. Во-вторых, клиенты постоянно будут запрашивать видео, а это значит, что сервер должен делать выборки кадров и отправлять их клиенту. Т.е. серверная платформа должна хорошо масштабироваться. Поэтому выбор серверной платформы однозначен – MS Azure.

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

  • Клиентская часть – Silverlight 3.0 (C#);
  • Сервер – MS Azure , Web Service, SQL Azure

Мы используем Silverlight ввиду интерактивной природы самого приложения. Известно, что MS Azure предоставляет несколько способов хранения данных. Мы останавливаемся на SQL Azure по двум причинам:

  1. Процесс разработки приложения мы хотим проводить без участия Azure, т.е. вести разработку обычного Silverlight-based клиент-серверного приложения, и в качестве хранилища данных использовать MS SQL. И только на последнем этапе разработки адаптировать приложение к MS Azure;
  2. Мы собираемся использовать свой собственный ORM компонент, который хорошо зарекомендовал себя при работе с MS SQL. При этом мы надеемся, что этот компонент будет также хорошо работать и с SQL Azure.

Вот конечный список требований к ПО для начала работы:

  • Supported Operating Systems: Windows 7; Windows Server 2008; Windows Server 2008 R2; Windows Vista Service Pack 1; Windows Vista Service Pack 2
  • IIS 7.0 (with ASP.NET, WCF HTTP Activation and optionally CGI)
  • Microsoft Visual Studio 2008 SP1, Microsoft Visual Studio 2010 Beta 2 or Microsoft Visual Web Developer 2008 Express Edition with SP1
  • Windows Azure Tools for Microsoft Visual Studio (November 2009) including Windows Azure SDK (http://www.microsoft.com/downloads/details.aspx?FamilyID=6967ff37-813e-47c7-b987-889124b43abd&displaylang=en)
  • Windows Azure Account
  • SQL Azure Account

Архитектура

Enterra WebCam Viewer – это клиент-серверное приложение, в котором применим следующее разделение на уровни (layers):

  • Data Provider Layer – уровень доступа к данным. На сервере источником данных является БД, на клиенте – интерфейс сервера. Таким образом, и на клиенте и на сервере мы будем использовать унифицированный интерфейс доступа к данным IDataProvider.
  • Business Objects Layer – уровень бизнес-объектов. Бизнес-объекты – это наиболее удобный способ получения и изменения данных, который абстрагирован от способа хранения и передачи данных. Бизнес-объекты учавствуют как на сервере так и на клиенте.
  • Business Logic – уровень бизнес логики на сервере. Под бизнес логикой мы понимаем обработку событий изменения или получения данных.

Описанная архитектура реализована с помощью нашего компонента Enterra.Data, который используется как на клиентской стороне, так и на серверной. Поэтому нам пришлось портировать Enterra.Data на Silverlight, это не вызвало у нас практически никаких проблем.
Из описанной выше функциональности Enterra WebCam Viewer формируется следующая объектная модель приложения:

  • User – бизнес-объект для хранения свойств пользователя (логин, пароль, e-mail);
  • Image Source – бизнес-объект соответствующий сущности источника изображений. Источник изображений – это абстракция веб-камеры. Свойства источника изображений – это адрес камеры, состояние (пауза, запись), ссылка на пользователя-владельца, уровень доступа к камере (доступна всем или только его владельцу;
  • Image Data – бизнес-объект для хранения изображения взятого с веб-камеры. Свойствами Image Data являются бинарные данные самого изображения, дата создания, ссылка на источник изображения.

Схема БД полностью соответствует объектной модели и приведена на Рис. 1.


Рис. 1. Схема БД для Enterra WebCam Viewer.

Взаимодействие с сервером

Как мы уже сказали в описании архитектуры – клиент взаимодействует с сервером посредством интерфейса IDataProvider. Т.е. наш сервер – это и есть имплементация IDataProvider. Приведем описание наиболее значимых методов IDataProvider:

//getting identificator for a new object of the specified type.
object GetNewId(Type type)

//load of object properties with specified identificator and type.
NameValueDictionary LoadData(Type type, object id)

//load of properties massive for objects of the specified type.
//Objects selection on server is done using a specified filter
//with specified sorting means.
NameValueDictionary[] LoadData(Type type, Filter filter, Order order)

//saving changes in objects
void Save(ChangedData[] changes)

Понятно, что имплементация IDataProvider на клиенте должна в свою очередь передавать вызовы методам вэб-сервиса. Мы не стали создавать на веб-сервисе несколько методов, вместо этого наш веб-сервис публикует один метод, посредством которого возможны вызовы всех методов сервера. Вот его сигнатура:

object InvokeAny(string methodName, object[] args)

В создании только одного метода веб-сервиса есть определенные плюсы:

  • И на клиенте и на сервере мы имеем центральное место обработки вызова. Это удобно например для обработки исключений или логирования.
  • Проблемы с передачей аргументов разных типов сосредотачиваются только в одном методе, а не размазываются на весь сервис.
  • Настроив вызов всего лиш одного метода, мы абстрагируемся от технологии веб-сервисов. Если мы решим использовать например WCF, то нам легче будет перейти на WCF делая рефакторинг только в одном методе.

Мы столкнулись с еще одной большой проблемой. Используемый нами компонент Enterra.Data, и связанный с ним опыт создания клиент-серверных приложений предполагает синхронную модель вызова методов сервера. Т.е. при вызове любого метода IDataProvider при выходе всегда получаем результат (или исключение). В Silverlight же синхронные вызовы невозможны, поэтому использование клиент-серверного компонента с синхронной парадигмой вызовов – это проблема, которая требует решения. Переделывать компонент с синхронной парадигмой в компонент с асинхронными вызовами – не приемлемо.

Мы решили проблему следующим образом:

  • Для использование Enterra.Data мы имплементировали IDataProvider делая асинхронные вызовы на сервер. Синхронность же вызовов IDataProvider достигается вставкой кода с циклом ожидания ответа.
  • Так как получение результата с сервера на Silverlight делается в основном потоке, то нельзя делать непосредственные вызовы к серверу в обработчиках UI событий. Для этого мы создали класс SyncInvoker который принимает два делегата: 1й делегат содержит код с вызовами на сервер, 2й делегат вызывается по завершению первого. SyncInvoker запускает 1й делегат в отдельном потоке и выходит, 2й делегат запускается по завершении 1го.

Таким образом мы смогли применить компонент с синхронной моделью вызова в асинхронной среде.

Видео запись с камер

Основная задача сервера – постоянно брать изображения с веб-камер, которые находятся в состоянии «Запись», и сохранять их в БД. Для этого на сервере должен постоянно работать процесс инициализирующий новое событие обработки камер. В Windows Server 2003, например это может быть windows-service вызывающий с определенным интервалом метод обработки камер. В MS Azure эта задача так же решается написанием цикла с вызовом метода обработки через определенный интервал. Далее этот код должен быть запущен под worker role.
Общий алгоритм обработки камер в терминах нашей объектной модели можно написать следующим образом:

  1. Запросить все объекты ImageSource с состоянием «Запись» и требующих записи следующего кадра;
  2. Для каждого запрошенного ImageSource получаем изображение;
  3. Создаем новый объект ImageData c полученным изображением;
  4. Сохраняем в ImageSource дату-время последнего взятия кадра и ссылку на сделанный ImageData ( поле LastImageId – хранит ссылку на последний кадр).

Прокомментируем подробнее слова «требующих записи следующего кадра» из 1го пункта. Каждый ImageSource имеет частоту кадров и хранит дату-время последнего взятия кадра. На основании этих свойств и текущего времени легко получить условие необходимости взятия кадра в конкретный момент времени.

Заметим также, что при создании ImageData вместе с основным изображением мы сохраняем также уменьшенную его копию. Это нужно для того чтобы клиент мог запрашивать несколько изображений без существенной нагрузки канала связи.

Развертывание на MS Azure

Итак, мы разработали веб-приложение, протестировали и отладили его в тепличных условиях и теперь настала пора развернуть его на MS Azure.
Создаем БД, используя закладку SQL Azure на персональной странице (см. Рис. 2)


Здесь необходимо выставить правила для Firewall. В данном случае правило «Enterra Inc.» разрешает доступ к SQL Azure c адреса 82.200.57.181. Так же Microsoft рекомендует установить “Allow Microsoft Services access to this server”.
Для создания таблиц, индексов необходимо использовать SQLСMD. SQLCMD входит в состав Microsoft SQL Server и может быть найден в папке SQL Server. Например, в «Microsoft Sql Server 2008» эта утилита может быть найдена в папке «C:Program FilesMicrosoft SQL Server100ToolsBinn»
Параметры командной строки, для подключения к SQL Azure, указаны ниже.

SQLCMD.EXE -U [email protected]_name -P password -S server_name.database.windows.net -d db_name

Для создания структуры БД, используя скрипт, достаточно выполнить данную команду:
SQLCMD.EXE -U [email protected]_name -P password -S server_name.database.windows.net -d db_name -i filename

Работу в MS Visual Studio начинаем с создания проекта C#/Cloud Service/Windows Azure Cloud Service. Наш Azure проект будет состоять из ASP.NET Web Role проекта и Worker Role проекта. На ASP.NET Web Role мы будем хостить Web Service и Silverlight приложение.

Вам понравилась статья, и вы бы хотели отдать свой проект на разработку? Вы можете связаться с нами здесь