Warum und wie haben wir Babylon.js nach Azure migriert

Du arbeitest für ein Startup. Plötzlich zahlt sich dieses harte Jahr des Codierens aus - mit Erfolg kommt mehr Wachstum und die Nachfrage nach Ihrer Web-App.

In diesem Tutorial möchte ich demütig eine unserer jüngeren „Erfolgsgeschichten“ für unser WebGL-Open-Source-Gaming-Framework Babylon.js und seine Website verwenden. Wir haben uns sehr darauf gefreut, dass so viele Web-Gaming-Entwickler es ausprobieren. Aber um der Nachfrage gerecht zu werden, wussten wir, dass wir eine neue Webhosting-Lösung benötigen. 

Während sich dieses Lernprogramm auf Microsoft Azure konzentriert, gelten viele Konzepte für verschiedene Lösungen, die Sie möglicherweise bevorzugen. Wir werden auch die verschiedenen Optimierungen sehen, die wir vorgenommen haben, um die Ausgabebandbreite von unseren Servern zu Ihrem Browser so weit wie möglich zu begrenzen.

Einführung

Babylon.js ist ein persönliches Projekt, an dem wir seit über einem Jahr arbeiten. Da es sich um ein persönliches Projekt handelt (d. H. Zeit und Geld), haben wir die Website, Texturen und 3D-Szenen auf einer relativ günstigen Hosting-Lösung mit einer kleinen, dedizierten Windows / IIS-Maschine gehostet. Das Projekt begann in Frankreich, war aber schnell auf dem Radar mehrerer 3D- und Web-Spezialisten auf der ganzen Welt sowie einiger Spielestudios. Wir haben uns über das Feedback der Community gefreut, aber der Verkehr war überschaubar!

Zum Beispiel hatten wir zwischen Februar 2014 und April 2014 durchschnittlich 7.000 Nutzer pro Monat und durchschnittlich 16.000 Seiten pro Monat. Einige der Ereignisse, bei denen wir gesprochen haben, haben einige interessante Gipfel hervorgebracht:

Aber die Erfahrung auf der Website war immer noch gut genug. Das Laden unserer Szenen wurde nicht mit unglaublicher Geschwindigkeit erledigt, aber die Benutzer beschwerten sich nicht so sehr.

Vor kurzem jedoch entschied sich ein cooler Typ, unsere Arbeit in Hacker News zu teilen. Wir haben uns sehr über solche Neuigkeiten gefreut! Aber schauen Sie sich an, was mit den Verbindungen der Site passiert ist:

Spiel ist aus für unseren kleinen Server! Es hörte langsam auf zu arbeiten und die Erfahrung für unsere Benutzer war wirklich schlecht. Der IIS-Server verbrachte seine Zeit damit, große statische Assets und Bilder bereitzustellen, und die CPU-Auslastung war zu hoch. Als wir im Begriff waren, das auf Babylon.js laufende Assassin's Creed Pirates WebGL-Erlebnisprojekt zu starten, war es an der Zeit, mithilfe einer Cloud-Lösung zu einem besser skalierbaren professionellen Hosting zu wechseln.

Bevor wir jedoch unsere Hosting-Optionen überprüfen, lassen Sie uns kurz über die Besonderheiten unserer Engine und Website sprechen:

  1. Auf unserer Website ist alles statisch. Derzeit läuft kein serverseitiger Code.
  2. Unsere Szenen (.babylon JSON-Dateien) und Texturen (.png oder .jpeg) können sehr groß sein (bis zu 100 MB). Dies bedeutet, dass wir unbedingt die gzip-Komprimierung unserer .babylon-Szenedateien aktivieren mussten. In unserem Fall werden die Preise für die ausgehende Bandbreite stark indiziert.
  3. Das Einfügen in die WebGL-Zeichenfläche erfordert besondere Sicherheitsprüfungen. Sie können unsere Szenen und Texturen beispielsweise nicht von einem anderen Server laden, wenn CORS nicht aktiviert ist.

Credits: Ich möchte mich besonders bedanken Benjamin Talmard, einer unserer französischen technischen Azure-Evangelisten, der uns beim Umzug nach Azure half.

1. Umstieg auf Azure-Websites und den Autoscale-Service

Da wir die meiste Zeit mit dem Schreiben von Code und Funktionen für unsere Engine verbringen möchten, möchten wir keine Zeit mit den Rohrleitungen verlieren. Deshalb haben wir uns sofort für einen PaaS-Ansatz und nicht für einen IaaS-Ansatz entschieden.

Darüber hinaus mochte uns die Integration von Visual Studio in Azure. Ich kann fast alles von meiner Lieblings-IDE aus machen. Selbst wenn Babylon.js auf GitHub gehostet wird, verwenden wir Visual Studio 2013, TypeScript und Visual Studio Online, um unsere Engine zu codieren. Als Hinweis für Ihr Projekt erhalten Sie die kostenlose Visual Studio Community und eine Azure-Testversion.

Der Umzug nach Azure dauerte ungefähr fünf Minuten:

  1. Ich habe auf der Admin-Seite eine neue Website erstellt: http://manage.windowsazure.com (könnte auch in VS ausgeführt werden).  
  2. Ich habe das richtige Changeset aus unserem Quellcode-Repository genommen, das der aktuell online verfügbaren Version entspricht.
  3. Ich habe mit der rechten Maustaste auf das Webprojekt im Visual Studio Solution Explorer geklickt.

Nun kommt die Großartigkeit der Werkzeuge. Da ich über ein an mein Azure-Abonnement gebundenes Microsoft-Konto bei VS angemeldet war, ließ mich der Assistent einfach die Website auswählen, auf der ich bereitstellen möchte.

Sie brauchen sich nicht um komplexe Authentifizierung, Verbindungszeichenfolge oder was auch immer zu kümmern.

Next, Next, Next & Publish“Und ein paar Minuten später, am Ende des Upload-Vorgangs aller unserer Assets und Dateien, war die Website betriebsbereit!

Bei der Konfiguration wollten wir vom coolen Autoscale-Service profitieren. In unserem vorherigen Hacker News-Szenario hätte es sehr geholfen.

Zunächst wurde Ihre Instanz in konfiguriert Standard Modus in der Rahmen Tab.

Dann können Sie bis wählen wie viele Instanzen Sie automatisch skalieren möchten, in welchen CPU-Bedingungen und auch zu welchen geplanten Zeiten. 

In unserem Fall haben wir uns entschlossen, bis zu drei kleine Instanzen (1 Kern, 1,75 GB Arbeitsspeicher) zu verwenden und eine neue Instanz automatisch zu erzeugen, wenn die CPU 80% ihrer Auslastung erreicht. Wir werden eine Instanz entfernen, wenn die CPU unter 60% fällt. In unserem Fall ist der Mechanismus für die automatische Skalierung immer aktiv. Wir haben keine bestimmten Uhrzeiten festgelegt.

Die Idee ist wirklich zu zahlen Sie nur für das, was Sie brauchen während bestimmter Zeiträume und Belastungen. Ich liebe das Konzept. Damit wären wir mit diesem Azure-Dienst in der Lage gewesen, frühere Peaks durch nichts zu bewältigen!

Sie haben auch einen schnellen Überblick über die Autoskalierungshistorie über die violette Grafik. In unserem Fall haben wir, seit wir zu Azure gewechselt sind, noch nie eine Instanz besprochen. Nachfolgend erfahren Sie, wie Sie das Risiko einer Autoskalierung minimieren können.

Um die Konfiguration der Website abzuschließen, wollten wir dies tun Aktivieren Sie die automatische GZIP-Komprimierung auf unseren spezifischen 3D-Engine-Ressourcen (.Babylon und .babylonmeshdata Dateien). Dies war für uns von entscheidender Bedeutung, da dadurch bis zu dreimal die Bandbreite eingespart werden konnteund damit… der Preis.

Websites werden auf IIS ausgeführt. Um IIS zu konfigurieren, müssen Sie in die web.config Datei. Wir verwenden in unserem Fall die folgende Konfiguration:

                                    

Diese Lösung funktioniert ziemlich gut und wir haben sogar festgestellt, dass die Ladezeit unserer Szenen im Vergleich zu unserem vorherigen Host verkürzt wurde. Ich vermute, das liegt an der besseren Infrastruktur und dem Netzwerk, das von Azure-Rechenzentren genutzt wird.

Ich habe jedoch schon länger darüber nachgedacht, nach Azure zu ziehen. Und meine erste Idee war nicht, dass Instanzen von Websites meine großen Assets unterstützen. Von Anfang an war ich mehr daran interessiert, mein Vermögen im Blob-Speicher besser zu lagern. Es würde uns auch ein mögliches CDN-Szenario bieten.

2. Verschieben von Assets in Azure Blob-Speicher, Aktivieren von CORS, Gzip-Support und CDN

Der Hauptgrund für die Verwendung von BLOB-Speicher ist in unserem Fall das Vermeiden des Ladens der CPU unserer Website-Instanzen, um diese zu bedienen. Wenn mit Ausnahme einiger HTML-, JavaScript- und CSS-Dateien alles über den Blob-Speicher bereitgestellt wird, haben unsere Website-Instanzen nur geringe Chancen zur automatischen Skalierung.

Dies wirft jedoch zwei Probleme auf, die gelöst werden müssen:

  1. Da der Inhalt auf einem anderen Domain-Namen gehostet wird, fallen wir in das domänenübergreifende Sicherheitsproblem. Um das zu vermeiden, müssen Sie das tun Aktivieren Sie CORS in der Remote-Domäne (Azure-Blob-Speicher).
  2. Azurblau Blob Storage unterstützt keine automatische GZIP-Komprimierung. Und wir möchten die CPU-Website-Nutzung nicht reduzieren, wenn wir im Gegenzug wegen der erhöhten Bandbreite den dreifachen Preis zahlen!

Aktivieren von CORS für den Blob-Speicher

CORS on Blob Storage wird seit einigen Monaten unterstützt. Dieser Artikel, Windows Azure Storage: Einführung in CORS, erläutert die Verwendung von Azure-APIs zum Konfigurieren von CORS. Auf meiner Seite wollte ich keine kleine App dafür schreiben. Ich habe im Internet bereits eines gefunden: Cynapta Azure CORS Helper - kostenloses Tool zum Verwalten der CORS-Regeln für Windows Azure Blob Storage.

Ich habe dann nur die Unterstützung für GET und die richtigen Header in meinem Container aktiviert. Um zu überprüfen, ob alles wie erwartet funktioniert, öffnen Sie einfach die F12-Entwicklerleiste und prüfen Sie die Konsolenprotokolle:

Wie Sie sehen, deuten die grünen Log-Linien darauf hin, dass alles gut funktioniert.

Hier ist ein Beispiel, in dem es fehlschlagen wird. Wenn Sie versuchen, unsere Szenen aus unserem Blob-Speicher direkt von Ihrem localhost-Rechner (oder einer anderen Domäne) zu laden, werden diese Fehler in den Protokollen angezeigt:

Fazit: Wenn Sie sehen, dass Ihre aufrufende Domain nicht in derAccess-Control-Allow-Origin"Header mit einem"Zugriff wird verweigert“Gleich danach, weil Sie Ihre CORS-Regeln nicht richtig festgelegt haben. Es ist sehr wichtig, Ihre CORS-Regeln zu kontrollieren; Andernfalls könnte jeder Ihr Vermögen und damit Ihre Bandbreite Geld kosten, ohne Sie wissen zu lassen! 

Aktivieren der Gzip-Unterstützung auf unserem Blob-Speicher

Wie ich dir schon gesagt habe, Azure Blob Storage unterstützt keine automatische GZIP-Komprimierung. Dies scheint auch bei Lösungen von Mitbewerbern wie S3 der Fall zu sein. Sie haben zwei Möglichkeiten, dies zu umgehen:

  1. Gzip die Dateien dich selbst auf dem Client vor dem Hochladen, Laden Sie es mit Ihren klassischen Werkzeugen in den Blob-Speicher hoch und stellen Sie das ein Inhaltskodierung Header zu gzip. Diese Lösung funktioniert, aber nur für Browser, die gzip unterstützen (gibt es immer noch einen Browser, der gzip überhaupt nicht unterstützt?). 
  2. Gzip die Dateien selbst auf dem Client und Laden Sie zwei Versionen in den Blob-Speicher hoch: eine mit der Standardeinstellung.Erweiterung und eins mit dem .extension.gzip, zum Beispiel. Richten Sie auf der IIS-Seite einen Handler ein, der die HTTP-Anforderung vom Client abfängt, und überprüfen Sie den Header akzept-encoding einstellen gzip und stellen Sie die entsprechenden Dateien bereit, die auf dieser Unterstützung basieren. Weitere Informationen zum zu implementierenden Code finden Sie in diesem Artikel: GZip-komprimierte Inhalte aus dem Azure-CDN bereitstellen.

In unserem Fall kenne ich keinen Browser, der WebGL und keine GZIP-Komprimierung unterstützt. Wenn der Browser gzip nicht unterstützt, besteht kein wirkliches Interesse daran, weiterzugehen, da dies wahrscheinlich bedeutet, dass auch WebGL nicht unterstützt wird.

Ich habe mich deshalb für die erste Lösung entschieden. Da wir nicht viele Szenen haben und nicht täglich neue Szenen produzieren, verwende ich derzeit diesen manuellen Prozess:

  1. Mit 7-zip komprimiere ich die.Babylon Dateien auf meinem Computer mit gzip-Codierung und „Komprimierungsgrad"Zu"am schnellsten”. Die anderen Komprimierungsstufen scheinen Probleme in meinen Tests hervorzurufen.
  2. Ich lade die Datei mit CloudBerry Explorer für Microsoft Azure Cloud Storage hoch.
  3. Ich habe den HTTP-Header manuell gesetzt Inhaltskodierung zu gzip mit CloudBerry.

Ich weiß was du denkst. Muss ich das für alle meine Dateien tun?!? Nein, Sie könnten an der Erstellung eines Tools oder eines Post-Build-Skripts arbeiten, das dies automatisieren würde. Hier ist zum Beispiel ein kleines Befehlszeilentool, das ich erstellt habe:

Zeichenfolge accountName = "yoda"; string containerName = "wwwbabylonjs"; string accountKey = "yourmagickey"; string sceneTextContent; // Erstes Argument muss das Verzeichnis im Azure-Blob-Container sein, auf das der String abgezielt wird. try StorageCredentials creds = neue StorageCredentials (Kontoname, Kontoschlüssel); CloudStorageAccount-Konto = neues CloudStorageAccount (creds, useHttps: true); CloudBlobClient client = account.CreateCloudBlobClient (); CloudBlobContainer blobContainer = client.GetContainerReference (containerName); blobContainer.CreateIfNotExists (); var sceneDirectory = blobContainer.GetDirectoryReference (Verzeichnis); string [] filesArgs = args.Skip (1) .ToArray (); foreach (Zeichenfolge Dateispezifikation in filesArgs) Zeichenfolge specdir = Path.GetDirectoryName (Dateispezifikation); Zeichenfolge specpart = Path.GetFileName (Dateispezifikation); if (specdir.Length == 0) specdir = Environment.CurrentDirectory;  foreach (String-Datei in Directory.GetFiles (specdir, specpart)) string path = Path.Combine (specdir, file); string sceneName = Pfad.GetFileName (Pfad); Console.WriteLine ("Working on" + sceneName + "…"); CloudBlockBlob blob = sceneDirectory.GetBlockBlobReference (sceneName); blob.Properties.ContentEncoding = "gzip"; blob.Properties.ContentType = "application / babylon"; sceneTextContent = System.IO.File.ReadAllText (Pfad); 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 ("Hochladen in" + Kontoname + "/" + Containername + "/" + Verzeichnis + "Fertig.");  catch (Ausnahme ex) Console.WriteLine (ex); 

Um es zu benutzen, könnte ich folgendes tun:

UploadAndGzipFilesToAzureBlobStorage Szenen / Espilit C: \ Boulot \ Babylon \ Szenen \ Espilit \*.Babylon* eine Szene schieben, die enthält mehrere Dateien (unsere inkrementellen szenen mit muliples .babylonmeshdata Dateien).

Oder einfach:

UploadAndGzipFilesToAzureBlobStorage Szenen / Espilit C: \ Boulot \ Babylon \ Szenen \ Espilit \Espilit.babylon a drücken eindeutige Datei.

Um zu überprüfen, ob gzip mit dieser Lösung wie erwartet funktioniert, verwende ich Fiddler. Laden Sie Ihren Inhalt von Ihrem Client-Computer und überprüfen Sie die Netzwerkablaufverfolgungen, ob der zurückgegebene Inhalt wirklich komprimiert ist und dekomprimiert werden kann:

CDN aktivieren

Wenn Sie die beiden vorherigen Schritte ausgeführt haben, müssen Sie auf der Azure-Verwaltungsseite nur auf eine Schaltfläche klicken, um das CDN zu aktivieren und es Ihrem Blob-Speicher zuzuordnen:

So einfach ist das! In meinem Fall muss ich einfach die folgende URL ändern: http://yoda.blob.core.windows.net/wwwbabylonjs/Scenes in http://az612410.vo.msecnd.net/wwwbabylonjs/Scenes. Beachten Sie, dass Sie diese CDN-Domäne an Ihre eigene anpassen können, wenn Sie möchten.

Dank dessen können wir Ihnen unsere 3D-Assets sehr schnell bereitstellen, da Sie von einem der hier aufgeführten Knotenstandorte aus bedient werden: Knotenpositionen des Azure Content Delivery Network (CDN).

Unsere Website wird derzeit im Nordeuropa-Azure-Datencenter gehostet. Wenn Sie jedoch aus Seattle kommen, senden Sie einen Ping-Befehl an diesen Server, um unsere grundlegenden Dateien index.html, index.js, index.css und ein paar Screenshots herunterzuladen. Alle 3D-Assets werden vom Seattle-Knoten in Ihrer Nähe bereitgestellt!

Hinweis: Alle unsere Demos verwenden die vollständig optimierte Erfahrung (Blob-Speicherung mit gzip, CDN und DB-Caching)..

3. Verwenden von HTML5 IndexedDB, um das erneute Herunterladen der Assets zu vermeiden

Die Optimierung der Ladezeiten und die Kontrolle der Kosten für die Ausgabebandbreite beziehen sich nicht nur auf den Server. Sie können auch eine Logik auf der Clientseite erstellen, um Dinge zu optimieren. Glücklicherweise haben wir das seit v1.4 unserer Babylon.js-Engine getan. Ich habe ausführlich erklärt, wie ich die Unterstützung implementiert habe IndexedDB In diesem Artikel: Verwenden von IndexedDB zum Umgang mit 3D-WebGL-Elementen: Teilen von Feedbacks und Tipps zu Babylon.JS. Wie Sie es in Babylon.js aktivieren können, erfahren Sie in unserem Wiki: Caching der Ressourcen in IndexedDB.

Grundsätzlich müssen Sie nur eine erstellen .babylon.manifest Datei, die mit dem Namen der übereinstimmt .Babylon Szene und legen Sie dann fest, was Sie zwischenspeichern möchten (Texturen und / oder JSON-Szene). Das ist es.

Überprüfen Sie beispielsweise, was in der Hill Valley-Demoszene vor sich geht. Beim ersten Laden werden die gesendeten Anforderungen gesendet:

153 Artikel und 43,33 MB erhalten. Aber wenn Sie Babylonjs.com angenommen habenVerwenden Sie zusätzlichen Speicher auf Ihrem Computer”, Hier sehen Sie das zweite Mal, wenn Sie dieselbe Szene laden:

1 Element und 348 Bytes! Wir prüfen nur, ob sich die Manifestdatei geändert hat. Wenn nicht, laden wir alles aus der Datenbank und wir sparen 43+ MB Bandbreite.

Zum Beispiel wird dieser Ansatz in den Assassin's Creed Pirates-Spielen verwendet:

Lass uns darüber nachdenken:

  • Das Spiel startet fast sofort nachdem es einmal geladen wurde, da die Assets direkt von der lokalen Datenbank bereitgestellt werden.
  • Ihr Webspeicher ist weniger beansprucht und es wird weniger Bandbreite verwendet-kostet Sie weniger Geld!

Das wird sowohl Ihre Benutzer als auch Ihren Chef zufrieden stellen!

Dieser Artikel ist Teil der Web-Dev-Tech-Serie von Microsoft. Wir freuen uns zu teilen Microsoft Edge und das Neue EdgeHTML-Rendering-Engine mit dir. Erhalten Sie kostenlose virtuelle Maschinen oder testen Sie remote auf Ihrem Mac, iOS, Android oder Windows-Gerät. http://dev.modern.ie/.