Мы только что завершили проведение конференции DotNetConf – нашей онлайн конференции сообщества разработчиков, которые любит платформу .NET и открытые проекты.
Все доклады конференции уже доступны по ссылке на официальном сайте.
Платформа конференции
Довольно забавно называть “платформой” наше ПО, на котором работала конференция, это звучит слишком “энтерпрайзно” и официально. В прошлом мы провели конференции aspConf и mvcConf с помощью спонсоров, которые оплачивали необходимые расходы. Мы использовали мощности Channel 9, студию и вещали видео из Сиэтла или через Live Meeting.
Однако, в этом году нам захотелось провести конференции как можно проще, дешевле и более распределенно. Мы хотели пригласить спикеров из любой временной зоны. Насколько это было дешево? Примерно в $10. Точный счет будет подсчитан позднее, нам просто хотелось поднять мощности, провести мероприятие и затем отказаться от полученных ресурсов.
Видео-трансляция и шаринг экрана
- в этом году мы используем Google Hangouts и их возможности "Hangouts On Air". Учетная запись dotnetconf в Google приглашает докладчика на Hang Out и отмечает функцию "on air" перед стартом трансляции. Затем мы используем Hangout Toolbox для того чтобы динамически добавить графику и имена докладчиков на изображение. Все докладчики устанавливают разрешение 1280×768, а живой поток может уменьшаться до 480p;
- Как только вы нажимаете "”Start Broadcast” для вас формируется ссылка на YouTube для живого потока. Когда вы нажмете “End Broadcast” записанное видео будет готово для просмотра в вашей учетной записи YouTube в течении нескольких минут. Организаторы видео-общения (я и Javier) нажимают “Hide in Broadcast” и затухают, уходя из эфира. Вы можете увидеть как я “ушел” на скриншоте ниже, я все еще невидимо присутствую, но появлюсь только тогда, когда это потребуется. После этого активным остается только один докладчик и его видео расширяется на весь экран, что нам и нужно;
- Важное замечание: вместо того чтобы применять один Hangout 8 часов подряд, мы запускали и останавливали новый Hangout для каждого докладчика. Это означает, что наши записи уже разделены на странице YouTube. Видео на YouTube можно обрезать с начала и конца, так что проблем со обработкой видео нет.
База данных
Сюрприз! Мы не использовали базы данных. Нам они не требовались. Мы запустили двухстраничный сайт с помощью ASP.NET Web Pages, который был написан в WebMatrix. Сайт работает в облаке Windows Azure, и так как наши наборы данных (докладчики, расписание, расположение потоков видео и т.д.) не сильно меняются мы положили эти данные в XML-файлы. Безусловно это база данных, но это база данных для бедных. Зачем платить за то, что нам не нужно?
Как мы обновляли “базу данных” в течение конференции? Приготовьтесь высказать свое мнение. Данные лежат в DropBox. (Да. они могут быть и на SkyDrive или любом URL, но мы использовали DropBox).
Наше веб-приложение стягивает данные по ссылкам из DropBox и кэширует их. Работает очень хорошо.
<appSettings> <add key="url.playerUrl" value="https://dl.dropboxusercontent.com/s/fancypantsguid/VideoStreams.xml" /> <add key="url.scheduleUrl" value="https://dl.dropboxusercontent.com/s/fancypantsguid/Schedule.xml" /> <add key="url.speakerUrl" value="https://dl.dropboxusercontent.com/s/fancypantsguid/Speakers.xml" /> <add key="Microsoft.ServiceBus.ConnectionString" value="Endpoint=sb://[your namespace].servicebus.windows.net;SharedSecretIssuer=owner;SharedSecretValue=[your secret]" /> </appSettings>
Код прост, каким и должен быть код. Хотите посмотреть на разметку расписания? Да, это <table>. Это таблица для расписания. Ня!
@foreach(var session in schedule) { var confTime = session.Time; var pstZone = TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time"); var attendeeTime = TimeZoneInfo.ConvertTimeToUtc(confTime, pstZone); <tr> <td> <p>@confTime.ToShortTimeString() (PDT)</p> <p>@attendeeTime.ToShortTimeString() (GMT)</p> </td> <td> <div class="speaker-info"> <h4>@session.Title</h4> <span class="company-name"><a class="speaker-website" href="/speakers.cshtml?speaker=@session.Twitter">@session.Name</a></span> <p>@session.Abstract</p> </div> </td> </tr> }
Масштабирование
Мы начали с экстрамаленького (термины Windows Azure – прим. перев.) экземпляра Windows Azure Web Site, а затем переключились на два больших экземпляра (в конце концов, мы откатились на два средних, так как большие экземпляры оказались чрезмерно мощными) Web Site.
Мы масштабировались вверх (и следовательно, платили больше) только в течение конференции и после ее проведения перевели сайт на маленькие экземпляры. Нет необходимости тратить деньги когда этого не требуется.
Обновление сайта в реальном времени с SignalR
Поскольку ссылка на трансляцию доклада YouTube меняется с каждым спикером, у нас была проблема того, что участники конференции должны были бы обновлять страницу в браузере для того, чтобы получить новый URL. Есть множество решений такого сценария, о которых вы могли подумать. Мы могли указать обновление через meta, обновление по таймеру, но все эти решения не выполняются по требованию. Кроме того, нам хотелось показывать заставки в течение смены спикера. Пока один из нас готовил следующего докладчика, зрители получали бы и смотрели видео-заставки.
Мы обнаружили для себя эту проблему около 22-00 за ночь до конференции. Javier и я пообщались по Скайпу и решили сделать следующий хак.
Что если у каждого будет клиент SignalR (библиотека взаимодействия сервера и клиента на HTML/JS в реальном времени – прим. перев.), запущенный во время просмотра видео? Тогда мы сможем отправить зрителям через пуш следующее видео прямо из консоли администрирования.
Давайте я поясню это. Есть зритель (вы), есть админ (я) и сервер (Узел). Зритель использует главную страницу со следующим кодом на JavaScript c библиотекой SignalR:
$(function () { var youtube = $.connection.youTubeHub; $.connection.hub.logging = true; youtube.client.updateYouTube = function (message, password) { $("#youtube").attr("src", "http://www.youtube.com/embed/" + message + "?autoplay=1"); }; $.connection.hub.start(); $.connection.hub.disconnected(function () { setTimeout(function () { $.connection.hub.start(); }, 5000); }); });
Зритель слушает, вернее, ожидает сообщение от SignalR с сервера с коротким кодом видео YouTube. Когда сообщение приходит, мы заменяем iFrame. Все просто и это работает.
Ниже разметка консоли администратора, через которую мы отправляем новый код видео YouTube ожидающим зрителям (я использую Razor из ASP.NET Web Pages и WebMatrix, так что это смешанный код HTML/JS):
<div id="container"> <input type="text" id="videoId" name="videoId"> <input type="text" id="password" name="passsword" placeholder="password"> <button id="playerUpdate" name="playerUpdate">Update Player</button> </div> @section SignalR { <script> $(function () { var youtube = $.connection.youTubeHub; $.connection.hub.logging = true; $.connection.hub.start().done(function () { $('#playerUpdate').click(function () { youtube.server.update($('#videoId').val(), $('#password').val()); }); }); $.connection.hub.disconnected(function() { setTimeout(function() { $.connection.hub.start(); }, 5000); }); }); </script> }
Мы отправляем короткий код и пароль. Все это должно быть достаточно сложно, а? Как же выглядит мощный бэкенд SignalR запущенный в облаке на базе Windows Azure Service Bus? Уверены, что код должен быть слишком большим, чтобы показать его в рамках блога, да? Расслабьтесь, друзья.
public class YouTubeHub : Microsoft.AspNet.SignalR.Hub { public void update(string message, string password) { if (password.ToLowerInvariant() == "itisasecret") { Clients.All.updateYouTube(message); ConfContext.SetPlayerUrl(message); } } }
Это одновременно и ночной кошмар пуриста и мечта прагматика. В любом случае, мы использовали этот код во время конференции и он работал. Между сессиями мы отправляли ссылки на записанные заранее ролики-заставки, а затем перед очередным докладом отправляли ссылку на его видео.
Кроме того, мы обновляли ссылки DropBox с текущими адресами видео-потоков, так чтобы новые посетители получали правильные ссылки на последние видео, так как новым посетителям было бы неправильно ждать очередного пуша со ссылкой на видео.
Что насчет масштабирования вверх? У нас была пара машин в ферме, так что нам требовалось чтобы SignalR пушил обновленные ссылки на видео с учетом масштабируемого решения. Это заняло еще 10 минут.
Масштабирование с SignalR с помощью шины сообщений Windows Azure Service Bus
Мы использовали SignalR 1.1 Beta плюс Azure Service Bus Topics для масштабирования и поэтому добавили Service Bus в нашу учетную запись Windows Azure. Код запуска нашего приложения изменился, был добавлен вызов метода UseServiceBus():
string poo = "Endpoint=sb://dotnetconf-live-bus.servicebus.windows.net/;SharedSecretIssuer=owner;SharedSecretValue=g57totalsecrets="; GlobalHost.DependencyResolver.UseServiceBus(poo,"dotnetconf"); RouteTable.Routes.MapHubs();
Теперь SignalR использует подписки Service Bus Topics для механизма “Публикации/Подписки” для того чтобы отправить пуш-уведомления между двумя веб-серверами. Я могу сделать пуш-отправку с сервера Web 1 и это сообщение будет доставлено всем подключенным как к серверу Web 1 так и к Web 2 (или Web N) через постоянное подключение SignalR в реальном времени.
Мы удалим этот Service Bus Topic как только закончим с конференцией. Очень бы не хотелось получить счет на еще несколько пятаков. 😉 Ниже представлены цены на этот сервис в Windows Azure:
432,000 сообщений Service Bus стоят 432,000/10,000 * $0.01 = 44 * $0.01 = $0.44 в день.
Не уверен в том, сколько сообщений использовали мы, но могу быть спокоен, что они не будут стоить нам много.
Благодарности сообществу!
- Большое спасибо дизайнеру Jin Yang, который создал логотип и дизайн dotnetConf. Поблагодарите его в твиттере @jzy. Спасибо Dave Ward за верстку дизайна в HTML!
- Благодарности и почтение Javier Lozano за кодинг, его организованность, его брейнштормы и его безустанную тяжелую работу. Спасибо ему за то, что просидел со мной несколько часов ночью, пока мы писали SignalR_код и обновляли сайт DotNetConf.net;
- Спасибо David Fowler за фразу “добавить Service Bus занимает всего 10 минут”;
- Спасибо Eric Hexter и Jon Galloway за их организаторские способности и потраченное время на все конференции *Conf!
- Но больше всего я хочу поблагодарить докладчиков, которые потратили свое время и сделали доклады, а так же сообщество, которое подключилось к трансляции и общению!
ссылка на оригинал статьи http://habrahabr.ru/post/178193/
Добавить комментарий