Статьи

Почему и как мы мигрировали babylon.js в Azure: CORS, gzip и IndexedDB

Эта статья является частью серии технологий веб-разработки от Microsoft. Спасибо за поддержку партнеров, которые делают возможным использование SitePoint.

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

В этом уроке я хочу смиренно использовать одну из наших недавних историй успеха, связанных с нашей игровой платформой с открытым исходным кодомWebGL, babylon.js и ее веб-сайт: babylonjs.com . Мы были рады увидеть, как многие разработчики веб-игр попробуют это.

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

Вступление

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

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

image1-март-апрель-пики

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

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

image2-март-пики

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

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

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

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

Шаг 1. Переход на веб-сайты Azure и сервис Autoscale

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

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

Переезд в Лазурный занял у меня примерно 5 минут:

  1. Я создал новый веб-сайт на странице администратора: http://manage.windowsazure.com (может быть сделано и внутри VS).
  2. Я взял правильный набор изменений из нашего репозитория исходного кода, соответствующий версии, которая была в данный момент онлайн.
  3. Я щелкнул правой кнопкой мыши веб-проект в обозревателе решений Visual Studio.
    image3 опубликуйте-скриншот
  4. Здесь приходит удивительный инструмент. Когда я вошел в VS с использованием учетной записи Microsoft, связанной с моей подпиской Azure, мастер позволил мне просто выбрать веб-сайт, на котором я хотел бы развернуть.
    image4-azzure-издательство-варианты

Не нужно беспокоиться о сложной аутентификации, строках соединения или чем-то еще.

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

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

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

image5-веб-хостинг-план-режим

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

image6-instace-варианты

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

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

Чтобы завершить настройку веб-сайта, мы хотели включить автоматическое сжатие 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.

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

Шаг 2. Перемещение ресурсов в хранилище BLOB-объектов Azure, включая CORS, поддержку gzip и CDN

Основная причина использования хранилища BLOB-объектов в нашем случае заключается в том, чтобы не загружать ЦП экземпляров нашего веб-сайта для их обслуживания. Если все обслуживается через хранилище больших двоичных объектов, за исключением нескольких файлов html, js & css, у экземпляров нашего веб-сайта будет мало шансов на автоматическое масштабирование.

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

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

Включение CORS в хранилище BLOB-объектов

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

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

image7-веб-разработчиков-инструменты-babylonjs

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

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

image8-контроль доступ-происхождение заголовок

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

Включение поддержки gzip в нашем хранилище BLOB-объектов

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

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

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

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

  1. Используя 7-zip , я .babylon файлы .babylon на моей машине, используя кодировку gzip и compression level для fastest . Другие уровни сжатия вызывают проблемы в моих тестах.
  2. Я загружаю файл с помощью CloudBerry Explorer для облачного хранилища Microsoft Azure .
  3. Я вручную установил content-encoding заголовка HTTP на gzip с CloudBerry.

image9-GZIP-в-исследователь

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

Чтобы использовать его, я мог бы сделать UploadAndGzipFilesToAzureBlobStorage Scenes/Espilit C:\Boulot\Babylon\Scenes\Espilit\*.babylon* UploadAndGzipFilesToAzureBlobStorage Scenes/Espilit C:\Boulot\Babylon\Scenes\Espilit\*.babylon* UploadAndGzipFilesToAzureBlobStorage Scenes/Espilit C:\Boulot\Babylon\Scenes\Espilit\*.babylon* чтобы протолкнуть сцену, содержащую несколько файлов (наши дополнительные сцены с файлами muliples.babylonmeshdata )

Или просто UploadAndGzipFilesToAzureBlobStorage Scenes/Espilit C:\Boulot\Babylon\Scenes\Espilit\Espilit.babylon чтобы UploadAndGzipFilesToAzureBlobStorage Scenes/Espilit C:\Boulot\Babylon\Scenes\Espilit\Espilit.babylon уникальный файл.

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

image10-регистрация GZIP-рабочий

Включение CDN

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

image11 включение-режим CDN

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

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

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

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

Шаг 3: Использование HTML5 IndexedDB, чтобы избежать повторной загрузки ресурсов

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

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

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

images12-запросы-сделанные впервые

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

images13-второй-запрос Babylon-манифест

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

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

images14-сайт-страницу пользователь-компьютер-хранилище

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

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

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