Почему и как мы перенесли Babylon.js в Azure

18 января 2018

Вы работаете для запуска. Внезапно этот тяжелый год кодирования окупится - успех приносит больше роста и спроса на веб-приложение для масштабирования.

В этом уроке я хочу смиренно использовать одну из наших последних «историй успеха» вокруг нашей игровой платформы WebGL с открытым исходным кодом Babylon.js и ее веб-сайта. Мы были рады видеть, как многие разработчики веб-игр тестируют это. Но чтобы не отставать от спроса, мы знали, что нам нужно новое решение для веб-хостинга.

Хотя этот учебник посвящен Microsoft Azure, многие из этих концепций относятся к различным решениям, которые вы, возможно, предпочтете. Мы также рассмотрим различные оптимизации, которые мы создали, чтобы максимально ограничить пропускную способность с наших серверов до вашего браузера.

Введение

Babylon.js - это персональный проект, над которым мы работаем уже более года. Поскольку это персональный проект (т. Е. Наше время и деньги), мы разместили веб-сайт, текстуры и 3D-сцены на относительно дешевом хостинговом решении, используя небольшую специализированную машину Windows IIS. Проект начался во Франции, но он быстро попал в радар нескольких 3D-специалистов и веб-специалистов по всему миру, а также некоторых игровых студий. Мы были довольны отзывами сообщества, но трафик был управляемым!

Например, в период с февраля 2014 года по апрель 2014 года у нас был средний месяц пользователей 7K +, в среднем на 16K + просматриваемых месяц. Некоторые из событий, о которых мы говорили, породили несколько интересных пиков:

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

Однако недавно классный парень решил поделиться своей работой с Hacker News. Мы были очень рады за такие новости! Но посмотрите, что случилось с соединениями сайта:

Игра для нашего маленького сервера! Он медленно прекратил работать, и опыт для наших пользователей был действительно плохим. Сервер IIS тратил свое время на обслуживание больших статических активов и изображений, а использование ЦП было слишком велико. Поскольку мы собирались запустить проект Assassin's Creed Pirates WebGL, работающий на Babylon.js, пришло время перейти на более масштабируемый профессиональный хостинг, используя облачное решение.

Но прежде чем рассматривать наши варианты хостинга, давайте кратко поговорим о специфике нашего движка и веб-сайта:

    На нашем сайте все статично. В настоящее время у нас нет серверного кода. Наши сцены (файлы.babylon JSON) и файлы текстур (.png или.jpeg) могут быть очень большими (до 100 МБ). Это означает, что нам абсолютно необходимо активировать сжатие gzip в наших файлах сцены.babylon. Действительно, в нашем случае цена будет сильно индексироваться по исходящей полосе пропускания. Для рисования в холсте WebGL необходимы специальные проверки безопасности. Например, вы не можете загружать наши сцены и текстуры с другого сервера без возможности CORS.

Кредиты: Я хотел бы поблагодарить Беньямина Тальмара, одного из наших французских технических лауреатов, которые помогли нам перейти на Лазурь.

1. Переход на Azure Web Sites и Autoscale Service

Поскольку мы хотели бы потратить большую часть нашего времени на разработку кода и функций для нашего движка, мы не хотим терять время на водопровод. Вот почему мы сразу решили выбрать подход PaaS, а не IaaS.

Кроме того, нам понравилась интеграция Visual Studio с Azure. Я могу делать почти все, начиная с моей любимой IDE. И даже если Babylon.js размещен на GitHub, мы используем Visual Studio 2013, TypeScript и Visual Studio Online для кодирования нашего движка. В качестве примечания для вашего проекта вы можете бесплатно получить участие в Visual Studio Community и Azure Trial.

Переход на Azure занял у меня примерно пять минут:

    Я создал новый веб-сайт на странице администратора: http: manage.windowsazure.com (может быть сделано и внутри VS). Я взял правильный набор изменений из нашего репозитория исходного кода, соответствующего версии, которая была в данный момент в сети. Я щелкнул правой кнопкой мыши веб-проект в обозревателе решений Visual Studio.

Теперь здесь приходит удивительность инструментария. Когда я был зарегистрирован в VS, используя учетную запись Microsoft, связанную с моей подпиской Azure, мастер позволил мне просто выбрать веб-сайт, на котором я хотел бы развернуть.

Не нужно беспокоиться о сложной проверке подлинности, строке подключения и т. Д.

«Next, Next, Next &Publish», а через пару минут, в конце процесса загрузки всех наших активов и файлов, веб-сайт запущен и работает!

На стороне конфигурации мы хотели воспользоваться отличной услугой автомасштабирования. Это очень помогло бы в нашем предыдущем сценарии Hacker News.

Во-первых, ваш экземпляр был настроен в стандартном режиме на вкладке «Масштаб».

Затем вы можете выбрать, сколько экземпляров вы хотите автоматически масштабировать, в каких условиях процессора, а также в какие запланированные времена.

В нашем случае мы решили использовать до трех небольших экземпляров (1 ядро, 1,75 ГБ памяти) и автоматически создавать новый экземпляр, если процессор использует более 80% его использования. Мы удалим один экземпляр, если процессор упадет ниже 60%. Механизм автомасштабирования всегда включен в нашем случае - мы не задали конкретные запланированные времена.

Идея состоит в том, чтобы действительно платить только за то, что вам нужно в определенные временные рамки и нагрузки. Мне нравится эта концепция. Благодаря этому мы смогли бы справиться с предыдущими пиками, ничего не сделав благодаря этой услуге Azure!

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

Чтобы завершить настройку веб-сайта, мы хотели включить автоматическое сжатие gzip для наших конкретных ресурсов 3D-движка (файлы.babylon и.babylonmeshdata). Это было важно для нас, поскольку это могло бы сэкономить до 3-х полос пропускания и, следовательно,... цены.

Веб-сайты работают в IIS. Чтобы настроить IIS, вам нужно войти в файл web.config. В нашем случае мы используем следующую конфигурацию:

<system.webServer>
  <staticContent>
    <mimeMap fileExtension=".dds" mimeType="application/dds" />
    <mimeMap fileExtension=".fx" mimeType="application/fx" />
    <mimeMap fileExtension=".babylon" mimeType="application/babylon" />
    <mimeMap fileExtension=".babylonmeshdata" mimeType="application/babylonmeshdata" />
    <mimeMap fileExtension=".cache" mimeType="text/cache-manifest" />
    <mimeMap fileExtension=".mp4" mimeType="video/mp4" />
  </staticContent>
  <httpCompression>
    <dynamicTypes>
      <clear />
      <add enabled="true" mimeType="text/*"/>
      <add enabled="true" mimeType="message/*"/>
      <add enabled="true" mimeType="application/x-javascript"/>
      <add enabled="true" mimeType="application/javascript"/>
      <add enabled="true" mimeType="application/json"/>
      <add enabled="true" mimeType="application/atom+xml"/>
      <add enabled="true" mimeType="application/atom+xml;charset=utf-8"/>
      <add enabled="true" mimeType="application/babylonmeshdata" />
      <add enabled="true" mimeType="application/babylon"/>
      <add enabled="false" mimeType="*/*"/>
    </dynamicTypes>
    <staticTypes>
      <clear />
      <add enabled="true" mimeType="text/*"/>
      <add enabled="true" mimeType="message/*"/>
      <add enabled="true" mimeType="application/javascript"/>
      <add enabled="true" mimeType="application/atom+xml"/>
      <add enabled="true" mimeType="application/xaml+xml"/>
      <add enabled="true" mimeType="application/json"/>
      <add enabled="true" mimeType="application/babylonmeshdata" />
      <add enabled="true" mimeType="application/babylon"/>
      <add enabled="false" mimeType="*/*"/>
    </staticTypes>
  </httpCompression>
</system.webServer>

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

Однако я подумывал о том, чтобы перебраться в Лазурь на некоторое время. И моя первая идея заключалась не в том, чтобы позволить экземплярам веб-сайтов обслуживать мои большие активы. С самого начала я больше интересовался хранением моих активов в хранилище blob, лучше разработанным для этого. Это также предложит нам возможный сценарий CDN.

2. Перенос активов в хранилище Azure Blob, включение поддержки CORS, Gzip и CD

Основная причина использования хранилища blob в нашем случае заключается в том, чтобы избежать загрузки ЦП наших экземпляров веб-сайта для их обслуживания. Если все хранится через хранилище blob, за исключением нескольких файлов HTML, JavaScript и CSS, наши экземпляры веб-сайтов будут иметь мало шансов автомасштабировать.

Но это решает две проблемы:

    Поскольку контент будет размещен на другом доменном имени, мы столкнемся с проблемой междоменной безопасности. Чтобы этого избежать, вам необходимо включить CORS в удаленном домене (хранилище Azure Blob). Azure Blob Storage не поддерживает автоматическое сжатие gzip. И мы не хотим понижать использование веб-сайта процессора, если взамен мы платим в три раза больше цены из-за увеличенной пропускной способности!

Включение CORS в хранилище Blob

CORS на хранилище blob поддерживается в течение нескольких месяцев. Эта статья, Windows Azure Storage: введение в CORS, объясняет, как использовать API Azure для настройки CORS. На моей стороне я не хотел писать небольшое приложение, чтобы сделать это. Я нашел один в Интернете, уже написанный: Cynapta Azure CORS Helper - бесплатный инструмент для управления правилами CORS для Windows Azure Blob Storage.

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

Как видите, зеленые строки журнала подразумевают, что все работает хорошо.

Вот пример, в котором он потерпит неудачу. Если вы попытаетесь загрузить наши сцены из нашего хранилища blob непосредственно с вашей локальной машины (или любого другого домена), вы получите эти ошибки в журналах:

В заключение, если вы видите, что ваш домен вызова не найден в заголовке «Access-Control-Allow-Origin» с «Access denied» сразу после этого, это потому, что вы не правильно установили правила CORS. Очень важно контролировать ваши правила CORS; в противном случае любой может использовать ваши активы и, таким образом, вашу пропускную способность, стоимость денег, не давая вам знать!

Включение поддержки Gzip в нашем хранилище Blob

Как я уже говорил вам, Azure Blob Storage не поддерживает автоматическое сжатие gzip. Это также похоже на решения конкурентов, такие как S3. У вас есть два варианта, чтобы обойти это:

    Gzip файлы самостоятельно на клиенте перед загрузкой, загрузить его в хранилище blob с помощью классических инструментов и установить заголовок кодировки содержимого для gzip. Это решение работает, но только для браузеров, поддерживающих gzip (есть ли еще браузер, который не поддерживает gzip?). Gzip файлы сами на клиенте и загружать две версии в хранилище blob: один с расширением по умолчанию и один с.extension.gzip, например. Настройте обработчик на стороне IIS, который поймает HTTP-запрос от клиента, проверьте, что кодировка accept-encoding, установленная для gzip, и обслуживает соответствующие файлы на основе этой поддержки. Более подробную информацию о коде для реализации в этой статье вы найдете: Обслуживание сжатого содержимого GZip с Azure CDN.

В нашем случае я не знаю ни одного браузера, поддерживающего WebGL, а не сжатия gzip. Поэтому, если браузер не поддерживает gzip, нет никакой реальной заинтересованности в дальнейшем, так как это, вероятно, означает, что WebGL также не поддерживается.

Поэтому я выбрал первое решение. Поскольку у нас нет большого количества сцен, и мы не выпускаем новый каждый день, я в настоящее время используя этот ручной процесс:

    Используя 7-zip, я сжимаю файлы.babylon на своей машине с использованием gzip-кодирования и «уровень сжатия» до «самого быстрого». Другие уровни сжатия, похоже, создают проблемы в моих тестах. Я загружаю файл с помощью CloudBerry Explorer для Microsoft Azure Cloud Storage. Я вручную установил кодировку содержимого заголовка HTTP для gzip с помощью CloudBerry.

Я знаю, о чем вы думаете. Я собираюсь сделать это для всех моих файлов?!? Нет, вы могли бы работать над созданием скрипта или сценария пост-сборки, который бы автоматизировал это. Например, вот небольшой инструмент командной строки, который я создал:

string accountName = "yoda";
string containerName = "wwwbabylonjs";
string accountKey = "yourmagickey";
string sceneTextContent;
// First argument must be the directory into the Azure Blob Container targeted
string directory = args[0];
try
{
StorageCredentials creds = new StorageCredentials(accountName, accountKey);
CloudStorageAccount account = new CloudStorageAccount(creds, useHttps: true);
CloudBlobClient client = account.CreateCloudBlobClient();
CloudBlobContainer blobContainer = client.GetContainerReference(containerName);
blobContainer.CreateIfNotExists();
var sceneDirectory = blobContainer.GetDirectoryReference(directory);
string[] filesArgs = args.Skip(1).ToArray();
foreach (string filespec in filesArgs)
{
    string specdir = Path.GetDirectoryName(filespec);
    string specpart = Path.GetFileName(filespec);
    if (specdir.Length == 0)
    {
        specdir = Environment.CurrentDirectory;
    }
    foreach (string file in Directory.GetFiles(specdir, specpart))
    {
        string path = Path.Combine(specdir, file);
        string sceneName = Path.GetFileName(path);
        Console.WriteLine("Working on " + sceneName + "...");
        CloudBlockBlob blob = sceneDirectory.GetBlockBlobReference(sceneName);
        blob.Properties.ContentEncoding = "gzip";
        blob.Properties.ContentType = "application/babylon";
        sceneTextContent = System.IO.File.ReadAllText(path);
        var bytes = Encoding.UTF8.GetBytes(sceneTextContent);
        using (MemoryStream ms = new MemoryStream())
        {
            using (GZipStream gzip = new GZipStream(ms, CompressionMode.Compress, true))
            {
                gzip.Write(bytes, 0, bytes.Length);
            }
            ms.Position = 0;
            Console.WriteLine("Gzip done.");
            blob.UploadFromStream(ms);
            Console.WriteLine("Uploading in " + accountName + "/" + containerName + "/" + directory + " done.");
        }
    }
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}

Чтобы использовать его, я мог бы сделать следующее:

UploadAndGzipFilesToAzureBlobStorage Scenes Espilit C: BoulotBabylonScenesEspilit *.babylon * для создания сцены, содержащей несколько файлов (наши инкрементные сцены с файлами muliples.babylonmeshdata).

Или просто:

UploadAndGzipFilesToAzureBlobStorage Сцены Espilit C: BoulotBabylonScenesEspilitEspilit.babylon для создания уникального файла.

Чтобы проверить, что gzip работает как ожидалось, используя это решение, я использую Fiddler. Загрузите содержимое с клиентского компьютера и проверьте сетевые трассы, если возвращаемый контент действительно сжат и может быть несжатым:

Включение CD

После того, как вы выполнили два предыдущих шага, вам просто нужно нажать на одну кнопку на странице администрирования Azure, чтобы включить CDN и сопоставить ее с вашим хранилищем памяти:

Все просто! В моем случае мне нужно просто изменить следующий URL-адрес: http: yoda.blob.core.windows.net wwwbabylonjs Сцены к http: az612410.vo.msecnd.net wwwbabylonjs Сцены. Обратите внимание, что вы можете настроить этот домен CDN самостоятельно, если хотите.

Благодаря этому мы можем очень быстро обслуживать ваши 3D-объекты, так как вам будет подан один из перечисленных ниже узлов: Azure Content Delivery Network (CDN).

Наш веб-сайт в настоящее время размещен в центре данных Azure Северной Европы. Но если вы едете из Сиэтла, вы будете пинговать этот сервер, чтобы загрузить наши базовые файлы index.html, index.js, index.css и пару скриншотов. Все 3D-активы будут обслуживаться с узла Сиэтла рядом с вами!

Примечание. Все наши демонстрации используют полностью оптимизированный опыт (хранилище blob с использованием gzip, CDN и кэширования DB).

3. Использование HTML5 IndexedDB для предотвращения повторной загрузки активов

Оптимизация времени загрузки и ограничение затрат на пропускную способность не только на стороне сервера. Вы также можете создать некоторую логическую клиентскую сторону для оптимизации работы. К счастью, мы это сделали с v1.4 нашего двигателя Babylon.js. Я подробно объяснил, как я реализовал поддержку IndexedDB в этой статье: Использование IndexedDB для обработки ваших 3D-ресурсов WebGL: обмен отзывами и советами Babylon.JS. И вы узнаете, как активировать его в Babylon.js на нашей вики: кэширование ресурсов в IndexedDB.

В принципе, вам просто нужно создать файл.babylon.manifest, соответствующий названию сцены.babylon, а затем установить то, что вы хотите кэшировать (текстуры и сцена JSON). Это оно.

Например, проверьте, что происходит с демо-сценой Hill Valley. В первый раз, когда вы загрузите его, вот отправленные запросы:

153 пункта и 43.33 МБ. Но если вы согласились разрешить babylonjs.com «использовать дополнительное хранилище на своем компьютере», вот что вы увидите во второй раз, когда вы загрузите ту же сцену:

1 элемент и 348 байт! Мы просто проверяем, изменился ли файл манифеста. Если нет, мы загружаем все из БД, и мы сохраняем пропускную способность 43 МБ.

Например, этот подход используется в играх Assassin's Creed Pirates:

Давайте подумаем об этом:

Игра запускается почти сразу после ее загрузки один раз, поскольку активы обслуживаются непосредственно из локальной базы данных, Ваше хранилище в Интернете менее напряжено и используется меньшая пропускная способность - вам стоит меньше денег!

Теперь это удовлетворит как ваших пользователей, так и вашего босса!

Эта статья является частью серии веб-технологий от Microsoft. Мы рады поделиться с вами Microsoft Edge и новым механизмом рендеринга EdgeHTML. Получайте бесплатные виртуальные машины или проверяйте удаленно на своем Mac, iOS, Android или устройстве Windows @ http: dev.modern.ie.