De ce și cum am migrat Babylon.js la Azure

Lucrezi pentru o pornire. Dintr-o dată, acel an greu de codificare este de plată - cu succes vine mai mult creșterea și cererea pentru aplicația dvs. web la scară.

În acest tutorial, vreau să folosesc cu umilință una dintre cele mai recente "povesti de succes" în jurul gamei WebGL de jocuri open source, Babylon.js și site-ul său web. Am fost entuziasmați să vedem atât de mulți dezvoltatori de jocuri pe web încercând-o. Dar pentru a ține pasul cu cererea, am știut că avem nevoie de o nouă soluție de găzduire web. 

În timp ce acest tutorial se concentrează pe Microsoft Azure, multe dintre concepte se aplică diferitelor soluții pe care le preferați. De asemenea, vom vedea diferitele optimizări pe care le-am implementat pentru a limita cât mai mult posibil lățimea de bandă de ieșire de la serverele noastre la browserul dvs..

Introducere

Babylon.js este un proiect personal pe care am lucrat acum mai bine de un an. Deoarece este un proiect personal (adică timpul și banii noștri), am găzduit site-ul, texturile și scenele 3D pe o soluție relativ ieftină de găzduire, folosind o mașină mică / dedicată Windows / IIS. Proiectul a început în Franța, dar a fost rapid pe radarul mai multor specialiști 3D și web din întreaga lume, precum și a unor studiouri de jocuri. Am fost mulțumiți de feedbackul comunității, dar traficul a fost ușor de gestionat!

De exemplu, între februarie 2014 și aprilie 2014, am avut o medie de 7K + utilizatori / lună cu o medie de 16K + pagini vizualizate / lună. Unele dintre evenimentele la care am vorbit au generat câteva vârfuri interesante:

Dar experiența de pe site a fost încă destul de bună. Încărcarea scenelor noastre nu a fost făcută cu viteză mare, dar utilizatorii nu se plângeau atât de mult.

Cu toate acestea, recent, un tip grozav a decis să ne împărtășească lucrul la Hacker News. Am fost cu adevărat fericiți pentru astfel de știri! Dar uita-te la ce sa intamplat cu conexiunile site-ului:

Joc încheiat pentru serverul nostru mic! A încetat încet să lucreze, iar experiența pentru utilizatorii noștri a fost foarte rău. Serverul IIS și-a petrecut timpul oferind bunuri și imagini statice mari, iar utilizarea procesorului a fost prea mare. Pe măsură ce urmaam lansarea proiectului Assassin's Creed Pirates WebGL, care se desfășura pe Babylon.js, a trebuit să trecem la o găzduire profesională mai scalabilă, folosind o soluție cloud.

Dar, înainte de a revizui opțiunile de găzduire, să discutăm pe scurt despre specificul motorului și site-ului nostru:

  1. Totul este static pe site-ul nostru. În prezent nu avem niciun cod de pe server.
  2. Scenele noastre (fișiere .babylon JSON) și texturi (.png sau .jpeg) pot fi foarte mari (până la 100 MB). Aceasta înseamnă că este absolut necesar să activați compresia gzip pe fișierele noastre de scenă .babylon. Într-adevăr, în cazul nostru, prețul va fi indexat foarte mult pe lățimea de bandă de ieșire.
  3. Desenarea în panza WebGL necesită verificări speciale de securitate. Nu puteți încărca scenele și texturile de pe alt server fără CORS activat, de exemplu.

Credite: Aș dori să mulțumesc în mod special Benjamin Talmard, unul dintre francezii noștri francezi Azure, care ne-au ajutat să ne mutăm la Azure.

1. Mutarea pe site-urile web Azure & Serviciul Autoscale

Așa cum am vrea să ne petrecem cea mai mare parte a timpului nostru scriind codul și caracteristicile pentru motorul nostru, nu vrem să pierdem timpul în instalații sanitare. De aceea am decis imediat să alegem o abordare PaaS și nu una de tip IaaS.

Mai mult, ne-a plăcut integrarea Visual Studio cu Azure. Pot face aproape totul de la IDE-ul meu preferat. Și chiar dacă Babylon.js este găzduit pe GitHub, folosim Visual Studio 2013, TypeScript și Visual Studio Online pentru a ne codifica motorul. Ca o notă pentru proiectul dvs., puteți obține comunitatea Visual Studio și un test Azure gratuit.

Mutarea la Azure mi-a luat aproximativ cinci minute:

  1. Am creat un nou site web în pagina admin: http://manage.windowsazure.com (ar putea fi făcut și în interiorul VS).  
  2. Am luat setul de modificări corecte din depozitul nostru de cod sursă care corespunde versiunii care a fost online în prezent.
  3. Am făcut clic dreapta pe proiectul Web din Visual Studio Solution Explorer.

Acum vine minunata scule. Pe măsură ce eram conectat (ă) la VS utilizând contul Microsoft legat de abonamentul meu Azure, vrăjitorul mi-a permis să aleg pur și simplu site-ul web pe care aș vrea să-l utilizez.

Nu trebuie să vă faceți griji în legătură cu autentificarea complexă, șirul de conexiuni sau orice altceva.

Următorul, Următorul, Următorul și publicat"Și câteva minute mai târziu, la sfârșitul procesului de încărcare a tuturor bunurilor și fișierelor noastre, site-ul a fost pus în funcțiune!

În ceea ce privește configurația, am dorit să beneficiem de serviciul de autoscrisă rece. Ar fi ajutat foarte mult în scenariul nostru anterior Hacker News.

În primul rând, instanța dvs. a fost configurată în Standard mod în Scară fila.

Apoi, puteți alege până la câte cazuri ați dori să scalați automat, în care condițiile CPU și, de asemenea, în ce orare programate. 

În cazul nostru, am decis să folosim până la trei mici instanțe (1 nucleu, memorie de 1,75 GB) și să lansăm o nouă instanță dacă procesorul depășește 80% din utilizarea sa. Vom elimina o instanță dacă procesorul scade sub 60%. Mecanismul de autoscalare se află întotdeauna în cazul nostru - nu am stabilit anumite ore programate.

Ideea este cu adevărat să plătiți doar pentru ceea ce aveți nevoie în anumite perioade și sarcini specifice. Îmi place conceptul. Cu asta, am fi putut să ne ocupăm de vârfurile anterioare făcând nimic datorită acestui serviciu Azure!

De asemenea, ați avut o vedere rapidă asupra istoricului autoscarnării prin diagrama purpurie. În cazul nostru, de când ne-am mutat la Azure, nu am trecut niciodată de o instanță până acum. Și vom vedea mai jos cum să minimalizăm riscul de a cădea într-o autoscalificare.

Pentru a încheia cu privire la configurația site-ului web, am vrut activați compresia automată gzip despre resursele noastre specifice de motor 3D (.babylon și .babylonmeshdata fișiere). Acest lucru a fost critic pentru noi, deoarece ar putea salva până la 3 ori lățimea de bandăși astfel ... prețul.

Site-urile web rulează pe IIS. Pentru a configura IIS, trebuie să intrați în web.config fişier. Folosim următoarea configurație în cazul nostru:

                                    

Această soluție funcționează destul de bine și am observat chiar că timpul pentru încărcarea scenelor a fost redus comparativ cu gazda noastră anterioară. Cred că asta este datorită infrastructurii și rețelei mai bune folosite de centrele de date Azure.

Cu toate acestea, m-am gândit să mă mut în Azure pentru o vreme. Și prima mea idee nu a fost aceea de a lăsa instanțele site-urilor web să-mi servească activele mari. De la început, am fost mai interesat să-mi stochez proprietățile în depozitul de blob mai bine conceput pentru asta. De asemenea, ne-ar oferi un posibil scenariu CDN.

2. Mutarea activelor în spațiul de stocare azorală Blob, activarea CORS, suportul Gzip și CDN

Motivul principal pentru utilizarea stocării blob în cazul nostru este de a evita încărcarea CPU-ului instanțelor site-ului nostru pentru a le servi. Dacă totul este servit prin memoria blob, cu excepția câtorva fișiere HTML, JavaScript și CSS, instanțele site-ului nostru web vor avea puține șanse de autoscale.

Dar acest lucru ridică două probleme pentru a rezolva:

  1. Pe măsură ce conținutul va fi găzduit pe un alt nume de domeniu, vom intra în problema de securitate încrucișată. Pentru a evita acest lucru, trebuie să faceți asta activați CORS pe domeniul de la distanță (Depozit blister Azure).
  2. Azur Memoria Blob nu suportă compresia automată a gzip-urilor. Și nu vrem să micșorăm utilizarea site-ului Web al CPU dacă în schimb plătim de trei ori prețul din cauza lărgimii de bandă mărită!

Activarea CORS pe spațiul de stocare blob

CORS pe depozitul de blob a fost susținut pentru câteva luni acum. Acest articol, stocarea Windows Azure: Introducerea CORS, explică modul de utilizare a API-urilor Azure pentru a configura CORS. Pe partea mea, nu am vrut să scriu o mică aplicație pentru a face asta. Am găsit pe web deja scris: Cynapta Azure CORS Helper - instrument gratuit pentru administrarea regulilor CORS pentru Windows Azure Blob Storage.

Apoi am activat suportul pentru GET și anteturile corespunzătoare pe containerul meu. Pentru a verifica dacă totul funcționează așa cum era de așteptat, deschideți pur și simplu bara de dezvoltatori F12 și verificați jurnalele consolei:

După cum puteți vedea, liniile verde din jurnal presupun că totul funcționează bine.

Iată un exemplu de caz în care acesta va eșua. Dacă încercați să încărcați scenele din depozitul nostru blob direct de la mașina localhost (sau orice alt domeniu), veți primi aceste erori în jurnale:

În concluzie, dacă vedeți că domeniul dvs. de apelare nu este găsit în secțiunea "Access-Control-Allow-Origine"Cu un"Accesul este interzis"Imediat după aceea, este pentru că nu ați stabilit corect regulile CORS. Este foarte important să vă controlați regulile CORS; în caz contrar, oricine ar putea să vă folosească activele și, prin urmare, lățimea de bandă, costând bani fără să vă anunțe! 

Activarea suportului Gzip pe spațiul nostru de stocare a bloburilor

Așa cum ți-am spus înainte, Azure Blob Storage nu suportă compresia automată a gzip. De asemenea, pare să fie cazul soluțiilor concurenților, cum ar fi S3. Aveți două opțiuni pentru a rezolva problema:

  1. Gzip fișierele tu pe client înainte de încărcare, încărcați-l în spațiul de stocare blob folosind instrumentele dvs. clasice și setați-l Conținutul de codificare header la gzip. Această soluție funcționează, dar numai pentru browsere care acceptă gzip (există încă un browser care nu suportă gzip oricum?). 
  2. GZip fișierele pe cont propriu și pe client încărcați două versiuni în memoria blob: una cu valoarea implicită.extensie și una cu .extension.gzip, de exemplu. Configurați un handler din partea IIS care va prinde cererea HTTP de la client, verificați antetul accepta-codificare setat la gzip și să servească fișierele corespunzătoare bazate pe acest suport. Veți găsi mai multe detalii despre codul de implementat în acest articol: Servirea conținutului comprimat GZip de pe CDN Azure.

În cazul nostru, nu cunosc niciun browser care să suporte WebGL și nu compresia gzip. Deci, dacă browserul nu acceptă gzip, nu există nici un interes real să meargă mai departe, deoarece probabil acest lucru înseamnă că WebGL nu este acceptat nici.

Prin urmare, am ales prima soluție. Deoarece nu avem o mulțime de scene și nu producem unul nou în fiecare zi, folosesc în prezent acest proces manual:

  1. Folosind 7-zip, comprim.babylon fișierele de pe aparatul meu folosind codarea gzip și "nivel de compresie" la "cel mai rapid“. Celelalte niveluri de compresie par să genereze probleme în testele mele.
  2. Am încărcat fișierul utilizând CloudBerry Explorer pentru stocarea cloud-ului Microsoft Azure.
  3. Am setat manual antetul HTTP Conținutul de codificare la gzip cu CloudBerry.

Știu la ce te gândești. O să fac asta pentru toate fișierele mele?!? Nu, puteți lucra la construirea unui instrument sau a unui script care să automatizeze acest lucru. De exemplu, aici este un mic instrument de linie de comandă pe care l-am construit:

șirul contName = "yoda"; string containerName = "wwwbabylonjs"; string contKey = "yourmagickey"; șir șirTextContent; // Primul argument trebuie să fie directorul în Azure Blob Container șir direcționat direcționat = args [0]; încercați StorageCredentials creds = noi StorageCredentials (accountName, accountKey); Contul CloudStorageAccount = CloudStorageAccount nou (credințe, useHttps: true); CloudBlobClient client = account.CreateCloudBlobClient (); CloudBlobContainer blobContainer = client.GetContainerReference (containerName); blobContainer.CreateIfNotExists (); var scenaDirectory = blobContainer.GetDirectoryReference (director); șir [] fișiereArgs = args.Skip (1) .ToArray (); foreach (fișier string în fișiereArgi) string specdir = Path.GetDirectoryName (filespec); șir de caractere specpart = Path.GetFileName (filespec); dacă (specdir.Length == 0) specdir = Mediu.CurrentDirectory;  foreach (fișier șir în Directory.GetFiles (specdir, specpart)) string path = Path.Combine (specdir, file); șir scenăName = Path.GetFileName (calea); Console.WriteLine ("Lucrul la" + scenăName + "..."); CloudBlockBlob blob = scenaDirectory.GetBlockBlobReference (scenăName); blob.Properties.ContentEncoding = "gzip"; blob.Properties.ContentType = "aplicație / babylon"; sceneTextContent = System.IO.File.ReadAllText (calea); var octeți = Encoding.UTF8.GetBytes (sceneTextContent); folosind (MemorieStream ms = new MemoryStream ()) folosind (GZipStream gzip = nou GZipStream (ms, CompressionMode.Compress, true)) gzip.Write (octeți, 0, bytes.Length);  ms.Position = 0; Console.WriteLine ("Gzip făcut."); blob.UploadFromStream (ms); Console.WriteLine ("Încărcarea în" + accountName + "/" + containerName + "/" + director + "terminat");  captură (Excepție ex) Console.WriteLine (ex); 

Pentru ao folosi, aș putea face următoarele:

UploadAndGzipFilesToAzureBlobStorage Scene / Espilit C: \ Boulot \ Babilon \ Scene \ Espilit \* .Babylon * pentru a împinge o scenă care conține fișiere multiple (scenele noastre incrementale cu multiplii .babylonmeshdata fișiere).

Sau pur și simplu:

UploadAndGzipFilesToAzureBlobStorage Scene / Espilit C: \ Boulot \ Babilon \ Scene \ Espilit \Espilit.babylon pentru a împinge a un fișier unic.

Pentru a verifica dacă gzip funcționează conform așteptărilor folosind această soluție, folosesc fișierul Fiddler. Încărcați conținutul de la mașina dvs. client și verificați traseele de rețea dacă conținutul returnat este într-adevăr comprimat și poate fi necomprimat:

Activarea CDN

Odată ce ați realizat cei doi pași anteriori, trebuie doar să faceți clic pe un singur buton din pagina de administrare Azure pentru a activa CDN și să o cartografiați în spațiul de stocare a blob-ului:

Este atat de simplu! În cazul meu, trebuie doar să modificați următoarea adresă URL: http://yoda.blob.core.windows.net/wwwbabylonjs/Scenes la http://az612410.vo.msecnd.net/wwwbabylonjs/Scenes. Rețineți că puteți personaliza singur acest domeniu CDN dacă doriți.

Datorită acestui fapt, suntem capabili să vă oferim resursele noastre 3D într-un mod foarte rapid, deoarece veți fi difuzate dintr-una dintre locațiile de noduri listate aici: Locații de noduri de distribuire a conținutului în azure (CDN).

Site-ul nostru web este găzduit în prezent în datacenterul Azure Europa de Nord. Dar dacă veniți din Seattle, veți pinge acest server doar pentru a descărca fișierele index.html, index.js, index.css de bază și câteva screenshot-uri. Toate activele 3D vor fi servite de la nodul Seattle, aproape de dvs.!

Notă: Toate demosurile noastre utilizează experiența optimizată (depozitarea blob-ului folosind gzip, cache-ul CDN și DB).

3. Folosind indexedDB HTML5 pentru a evita re-descărcarea activelor

Optimizarea timpilor de încărcare și controlul costurilor de ieșire de bandă de ieșire nu sunt doar de partea serverului. De asemenea, puteți construi o parte logică a clientului pentru a optimiza lucrurile. Din fericire, am făcut asta de la versiunea 1.4 a motorului nostru Babylon.js. Am explicat în detaliu cum am implementat suportul IndexedDB în acest articol: Utilizarea IndexedDB pentru a vă ocupa de activele 3D WebGL: partajarea feedback-urilor și sugestiilor lui Babylon.JS. Și veți găsi cum să îl activați în Babylon.js pe wiki: Caching resursele în IndexedDB.

Practic, trebuie doar să creați o .babylon.manifest fișier care să corespundă numelui .babylon , apoi setați ceea ce doriți să cache (texturi și / sau scenă JSON). Asta e.

De exemplu, verificați ce se întâmplă cu scena demonstrativă Hill Valley. Prima dată când o încărcați, iată cererile trimise:

153 articole și 43,33 MB primite. Dar dacă ați acceptat să lăsați babylonjs.com "utilizați spațiu de stocare suplimentar pe computer", Iată ce veți vedea a doua oară când veți încărca aceeași scenă:

1 element și 348 de octeți! Verificăm doar dacă fișierul manifest a fost modificat. Dacă nu, vom încărca totul din DB și am salvat 43+ MB de lățime de bandă.

De exemplu, această abordare este folosită în jocurile Assassin's Creed Pirates:

Să ne gândim la asta:

  • Jocul se lansează aproape imediat după ce a fost încărcat o singură dată, deoarece activele sunt direcționate direct din DB-ul local.
  • Depozitul web este mai puțin stresat și este utilizată o lățime de bandă mai mică-vă costă mai puțini bani!

Acum, acest lucru va satisface atât utilizatorii dvs., cât și șeful dvs.!

Acest articol face parte din seriile de tehnologie web dev din Microsoft. Suntem încântați să împărtășim Microsoft Edge și noul EdgeHTML motor de randare cu tine. Obțineți mașini virtuale gratuite sau testați de la distanță pe dispozitivele Mac, iOS, Android sau Windows @ http://dev.modern.ie/.

Cod