De beste manier om een ​​Single Page Application (SPA) te hosten in Microsoft Azure

Traditionele Azure App Service versus Azure Functies V2 met proxy's versus Azure Storage Static Website (Preview)

Ik moet vaak statische websites implementeren (bijvoorbeeld onze bedrijfswebsite https://www.media-lesson.com) of Single Page-toepassingen en ik ben altijd op zoek naar manieren om de kosten en de implementatietijd te verbeteren.

Microsoft heeft onlangs een openbare preview van statische websitehosting voor Azure Storage aangekondigd en voegt nog een andere optie toe voor het hosten van een applicatie met één pagina (SPA) op Azure.

Net voordat Microsoft op 14 mei ondersteuning voor proxy's in de Azure Functions Runtime 2.0.11776-alpha heeft toegevoegd, biedt het een manier om een ​​statische website in Azure Storage te hosten en verkeer door te sturen via een Azure Function-proxyroute.

Beide nieuwe opties dragen bij aan de traditionele manier van hosten van (statische) websites in een Azure App Service. Er zijn nog meer opties voor het hosten van websites in Azure, b.v. met behulp van Containers, Docker, Kubernetes, virtuele machines enz. maar ik zal me blijven concentreren op eenvoudige en kostenefficiënte implementaties van toepassingen met één pagina.

En omdat we de hostingopties evalueren, is het ook de moeite waard om handmatige en automatische implementatie te vergelijken met behulp van Visual Studio Team Services (VSTS) voor de genoemde services.

Laten we deze vragen dus beantwoorden om te helpen beslissen welke service we gebruiken bij het hosten van een applicatie met één pagina:

  1. Hoeveel moeite kost het om een ​​app handmatig en automatisch te implementeren?
  2. Hoeveel configuratie is nodig?
  3. Hoe schaalt het?
  4. Hoe presteert het?
  5. Hoeveel kost het?

Test-app

Dus laten we dit experiment beginnen door een eenvoudige SPA te maken op basis van Angular met behulp van de Angular CLI als een test-app voor implementatie en testen op de 3 verschillende services: ng nieuwe testapp --routing Houd er rekening mee dat ik de routeringsfunctie direct aan de app toevoeg met de parameter --routing. Ik vind dit een belangrijk aspect om te testen bij het bekijken van hostingopties, omdat routing een configuratie-uitdaging kan zijn in sommige omgevingen zoals App Service, omdat we de webserver moeten configureren om routeafhandeling door onze client-app mogelijk te maken in plaats van serverzijde.

Om routing volledig te testen, hebben we ook enkele voorbeeldroutes nodig. Laten we daarom een ​​home en een about-component aan onze app toevoegen met behulp van de CLI: ng component component home en ng component about genereren. Vervolgens moeten we twee routes in onze app-routing.module.ts hebben om navigatie tussen de twee componenten mogelijk te maken:

Eindelijk enkele navigatieknoppen waarmee de gebruiker tussen de twee componenten in onze app.component.html kan navigeren:

Laten we onze app lokaal bouwen ter voorbereiding op handmatige implementatie met ng build --prod die ons deze kleine map met build-artefacten geeft:

Natuurlijk willen we de automatische implementatie ook drogen als onderdeel van een continu implementatieproces. Laten we daarom onze app naar een VSTS-repository duwen en een build-definitie instellen met deze 3 taken:

npm installeren

npm bouwen

Publiceer bouwartefacten van pad dist naar app

Azure App-service

Azure App Service is een PaaS-aanbod (Platform as a Service) en de klassieke manier om webinhoud op Azure te hosten. Met behulp van app-service moeten we de configuratie en schaalbaarheid van onze service met de hand verzorgen. Laten we om dit te testen een nieuwe app-service maken in de Azure Portal. Ik kies de S1-laag voor deze test omdat deze de instapniveau is voor productie-apps.

Routing configureren

Vanwege de aard van het PaaS-aanbod, zorgen ontwikkelaars voor de configuratie van de onderliggende webserver (in het geval van Windows is dit IIS). Dit betekent dat om routering in onze Angular-app mogelijk te maken, we een web.config-bestand moeten leveren met instructies voor de webserver over hoe om te gaan met routering of de angular-app in een ASP.Net Core 2.1-app te hosten met de SpaServices-middleware ingeschakeld. Hier een eenvoudig voorbeeld van een web.config met SPA-routing:

Handmatige implementatie

Laten we voor handmatige implementatie gewoon FTP gebruiken om de inhoud van onze dist-map en web.config te uploaden naar de wwwroot-map van de app-service. De FTP-inloggegevens kunnen worden gedownload in de Azure-portal op het overzichtstabblad van de app-service door te klikken op "Publicatieprofiel ophalen".

Continue implementatie met Visual Studio Team Services

Het instellen van een releasedefinitie in VSTS om de app naar app-service te implementeren is vrij eenvoudig, omdat we slechts een lege releasedefinitie nodig hebben met één taak:

Om een ​​eindpunt van een FTP-service te configureren, klikken we op "Beheren" en voegen een nieuw generiek eindpunt toe met dezelfde referenties die worden gebruikt voor handmatige implementatie.

Azure-functies

In deze variant gaan we Azure Storage gebruiken als een goedkope winkel voor onze statische bestanden en een Azure Function-app met proxy's om de SPA aan de gebruiker te bedienen. Dit stelt ons in staat om automatisch te schalen (bij gebruik van het consumptieplan), onze SPA te combineren met andere functies (bijv. API-aanroepen) onder één domein en onze app serverloos te beheren.

We moeten dus een functie-app en een opslagaccount maken (automatisch gemaakt bij het maken van een functie-app). Vervolgens moeten we een blob-container met de naam 'web' maken in het opslagaccount waar we onze bestanden later naar zullen implementeren.

De routemagie gebeurt nu in de manier waarop we proxy's configureren om verzoeken van onze functie-app door te sturen naar het opslagaccount. Daarom hebben we 2 proxy's nodig:

De eerste die verzoeken doorstuurt naar de basis-URL naar onze index.html

en een tweede om aanvragen voor andere statische activa zoals javascript-bestanden of stylesheets door te sturen naar hun locatie in het opslagaccount.

Handmatige implementatie

Om handmatig te implementeren klikt u op "Containers" in het opslagaccount in de Azure-portal en selecteert u de "web" -container die we zojuist hebben gemaakt. Laten we nu de bestanden van de lokale build uploaden.

Continue implementatie met Visual Studio Team Services

Om dit te testen moeten we een tweede releasedefinitie in VSTS maken met de lege processjabloon en de taak AzureBlob File Copy toevoegen:

Azure Storage

Dit is de nieuwste optie die onlangs in de openbare preview ging. Het idee is om opslag te gebruiken om de SPA te hosten, omdat een echte webserver niet nodig is om alleen statische bestanden te leveren die in aanmerking komen voor deze variant voor het modewoord "serverloos". Laten we dus een nieuw opslagaccount maken (general purpose v2) en vervolgens de statische websitefunctie inschakelen:

Dit is alle configuratie die we nodig hebben. Opslag wordt automatisch geschaald en routing werkt ook direct. Het primaire eindpunt is de URL van onze SPA. Leuk!

Handmatige implementatie

Als u handmatig wilt implementeren, klikt u op "Containers" in het opslagaccount in de Azure-portal en selecteert u de container "$ web" (die automatisch wordt gemaakt wanneer de statische website wordt ingeschakeld). Laten we nu de bestanden van de lokale build uploaden:

En dat is het!

Continue implementatie met Visual Studio Team Services

Om dit te testen moeten we een derde releasedefinitie in VSTS maken met de lege processjabloon en de taak AzureBlob File Copy toevoegen:

Zorg ervoor dat u versie 2 * selecteert (voorbeeld), anders mislukt de deploy-wail omdat het teken "$" in de containernaam eerder niet was toegestaan.

Prestatie

Om een ​​idee te krijgen van de prestaties laten we wat artillerie.io belastingstests uitvoeren op onze 3 implementaties. Hier zijn mijn resultaten bij het afvuren van 1.000, 10.000 en 100.000 aanvragen:

Er is een drastisch prestatievoordeel bij het gebruik van Azure Storage en het vermijden van de webservercomponent terwijl Functies en App Service op een vergelijkbare snelheid draaien. Dit is logisch omdat beide dezelfde onderliggende infrastructuur delen. Ik ben een beetje verrast dat de Functie-app nog langzamer werkt dan de App-service.

Ik vind dit nog vreemder bij het vergelijken van de totale looptijd om de 100.000 aanvragen-test te voltooien. Het duurde ongeveer 46 seconden om Azure Storage te voltooien en 14 minuten en 27 seconden voor App Service en zelfs 17 minuten en 2 seconden voor de Functie-app. Ik had verwacht dat de Functie-app in de loop van de tijd sneller zou worden, omdat ik verwachtte dat deze automatisch automatisch zou schalen. Wat in dit scenario niet lijkt te werken.

We hebben dus een duidelijke winnaar in deze discipline: opslag is echt snel!

Kosten

Het is lastig om de kosten goed te krijgen, omdat ze allemaal verschillende factureringsmodellen hebben. Hier is mijn voorbeeldberekening voor maandelijkse kosten voor 100.000 aanvragen / dag in de regio West-Europa (waarvan ik niet 100% zeker weet dat deze volledig en nauwkeurig is!):

App-service

1x S1-exemplaar in West-Europa met Windows (1 core, 1,75 GB RAM, 50 GB opslag) = 61,56 € / maand

Functie-app (+ opslag)

Onze SPA bestaat uit 5 bestanden * 100.000 aanvragen per dag * 31 = 15.500.000 aanvragen per maand in totaal. De totale grootte van onze app is ongeveer 0,33 MB, goed voor 0,98 TB aan uitgaand verkeer per maand in totaal. De minimale uitvoeringstijd is 100 ms (wat voldoende zou zijn voor ons proxy-doel) want we kunnen 10 aanvragen / uitvoering als tweede verwerken.

1x functie-app met 1.550.000 uitvoeringen met een uitvoeringstijd van 1 sec per maand (elk minder dan 128 MB geheugen) voor het verwerken van de aanvragen die door de proxy's gaan = 0,17 € / maand

1x Opslag Algemeen doel V2 Blob Blob Storage-account met LRS-redundantie en hot access-laag. Capaciteit 1 GB (we hebben eigenlijk slechts 300 kb nodig, maar dat is de kleinste beschikbare grootte), 100 schrijfbewerkingen, 100 lijstbewerkingen, 15.500.000 leesbewerkingen en 0,98 TB gegevens ophalen = 5,64 € / maand

Totaal: 5,81 € / maand.

opslagruimte

Voor de opslag nemen we gewoon dezelfde berekening als hierboven:

1x Opslag Algemeen doel V2 Blob Blob Storage-account met LRS-redundantie en hot access-laag. Capaciteit 1 GB (we hebben eigenlijk slechts 300 kb nodig, maar dat is de kleinste beschikbare grootte), 100 schrijfbewerkingen, 100 lijstbewerkingen, 15.500.000 leesbewerkingen en 0,98 TB gegevens ophalen = 5,64 € / maand

Gevolgtrekking

  • Het hosten van een SPA in pure opslag is verreweg de goedkoopste en meest performante manier van werken in Azure
  • Het hosten van een SPA in een functie-app met proxy's brengt minimale extra kosten met zich mee, maar een enorme prestatiedaling. Dit is vreemd omdat ik horizontaal moet schalen. Ik zal hier zeker meer onderzoek doen ...
  • Het hosten van een SPA in een app-service vereist extra configuratie-inspanning om routering te ondersteunen (complexer worden in combinatie met bijvoorbeeld web-API's)

Het hosten van een SPA in opslag zou geen probleem moeten zijn voor ontwikkel-, test- en ensceneringssituaties, omdat het snel is in te stellen en in de meeste gevallen zelfs gratis is voor die scenario's. Ik heb nog geen nadelen gevonden, dus zal ik wat dieper duiken en kijken of we het ook in productie kunnen gebruiken.

Aarzel niet om feedback te geven.