Bijna iedereen in Nederland kent de Serious Request actie van 3FM en het Nederlands Rode Kruis. Wat weinig mensen weten is dat de afgelopen 2 edities voor een belangrijk deel op Windows Azure draaide. In deze presentatie wordt de architectuur achter de oplossing toegelicht, welke Azure componenten er gebruikt zijn. Wat we geleerd hebben van de eerste editie, wat we daarom aanpast hebben voor de tweede editie, en wat er nog meer mogelijk was omdat het Windows Azure platform zich in de tussentijd ook verder ontwikkeld heeft. Ook worden er veel ervaringen gedeeld waar je als ontwikkelaar tegen aan kan lopen bij het opzetten van een Windows Azure oplossing.
DSD-NL 2021 Delft-FEWS in de cloud - Schotmeijer en Ekkelenkamp
Techdays 2013 NL - Serious Request met Windows Azure
1.
2. Serious Request met Windows Azure
Michaël Hompus
Principal Developer, Winvision
3. Michaël Hompus
Principal Developer bij Winvision
Specialisaties zijn SharePoint, Windows 8 Store Apps,
Windows Phone 8 en Windows Azure
E-mail: michael.hompus@winvision.nl
Twitter: @eNeRGy164
Blog: http://blog.hompus.nl
4. Onderwijs Zorg Goede doelen
In 2012 met Serious Request finalist voor beste
Microsoft-oplossing voor goede doelen wereldwijd
5. Serious Request met Windows Azure
Na deze sessie…
• …weten jullie hoe wij Serious Request met
Windows Azure gerealiseerd hebben en welke
problemen en oplossingen we hierbij zijn
tegengekomen
• …kunnen jullie de tips en voorbeelden gebruiken
om zelf een high available en high performance
website op Windows Azure te hosten
7. Sinds 2004 organiseert 3FM de actie “3FM Serious Request”
Elke editie staat in het teken van een stille ramp die samen
met het Nederlandse Rode Kruis wordt uitgekozen
10. Het Nederlandse Rode Kruis
Sinds 2009 levert Winvision een Microsoft-platform
met SharePoint, Dynamics CRM en Dynamics AX aan
het Nederlandse Rode Kruis
Op dit platform worden regelmatig onderdelen
toegevoegd om de processen bij het Rode Kruis te
ondersteunen
11.
12. De vraag van het Rode Kruis
“We zoeken voor 3FM Serious Request een nieuwe
leverancier voor de plaataanvraag website.
Kan Winvision een module aan het platform
toevoegen om online platen aan te vragen?”
13. Wat zijn de functionele requirements?
• Een formulier om platen aan te vragen
• Een formulier om alleen te doneren
• Het Rode Kruis wil content beheren
• Het Rode Kruis wil donaties exporteren
• 3FM wil de aangevraagde platen inzien
• Aangepast formulier voor het callcenter
14. Wat waren de eerdere ervaringen?
Beschikbaarheid applicaties
Zware load & aanvallen op de site
Oorzaak: alle systemen stonden op dezelfde servers
Veel bezoekers op de website
ca. 500.000 unieke bezoekers & 60.000 donaties
Veel verschillende browsers en devices
Grote toestroom tijdens actie
Exponentiele groei van bezoekers naar het einde toe
Korte levensduur
De actie is maar een week op de radio
16. Waarom voor Windows Azure kiezen?
Beschikbaarheid applicaties
Loosely coupled architectuur in het “DNA” van de services
Updates uitrollen zonder down time
Veel bezoekers op de website
ASP.NET MVC met Razor voor hoge productiviteit
HTML5, CSS3 en jQuery voor compatibiliteit in browsers
Grote toestroom tijdens actie
Proactief meegroeien met de bezoekersaantallen
Mogelijkheid om “onbeperkt” hardware toe te voegen
Korte levensduur
Datacenters gehost en gemanaged door Microsoft
Geen hardware of licenties nodig
17. ARCHITECTUUR
Welke applicaties hebben we?
Welke kenmerken heeft de front- en backend?
Hoe verbinden we deze omgevingen?
Wat zijn voor- en nadelen van ontkoppelen?
18. Welke applicaties hebben we?
Website vraag een plaat aan
Website voor directe donatie
Website voor het callcenter
Beheersite voor Rode Kruis
Beheersite voor 3FM
19. Frontend Backend
Vraag een plaat aan NRK Beheersite
Blob
Storage
Directe Donatie Worker role
Queues SQL Database
Callcenter 3FM Beheersite
Shared
Cache
20. Welke kenmerken heeft de frontend?
• Anoniem verkeer
• Geen directe communicatie met de database
• Een transactie is afgerond als het bericht op
de Queue staat
• Data wordt gelezen van Blob Storage en uit
de Shared Cache
Geoptimaliseerd om te schalen
21. Welke kenmerken heeft de backend?
• Geautoriseerd verkeer
• Redundantie in servers is er alleen voor
beschikbaarheid
• Directe communicatie met de database
• Data wordt geschreven naar de Blob Storage
en de Shared Cache
Geoptimaliseerd om met data te werken
22. Hoe verbinden we deze omgevingen?
• Storage Queues
• Worker role
• SQL Database
• Blob Storage
• Shared Cache
23. Storage Queues
• Berichten worden pas van de Queue verwijderd
als ze succesvol verwerkt zijn
• Indien de server crasht zal het bericht later door
een andere server alsnog opgepakt worden
• Elke actie kost geld, ook als de Queue leeg is
Tip: Gebruik een “back-off” strategie om in tijden
van inactiviteit het aantal transacties te beperken
24. Back-off strategie voor queue’s
int currentBackoff = 0;
while (true) {
List<CloudQueueMessage> messages = cloudQueue.GetMessages(1).ToList();
if (messages.Any()) {
currentBackoff = 0; // Reset back off
foreach (CloudQueueMessage message in messages) {
cloudQueue.DeleteMessage(message); // We zijn klaar, verwijder het bericht
}
} else {
// Er zijn geen berichten, ga 2 seconde langer wachten
if (currentBackoff < 300) { currentBackoff = currentBackoff + 2 };
Thread.Sleep(TimeSpan.FromSeconds(currentBackoff));
}
}
25. Blob Storage
• Zowel beschikbaar voor privé als publieke bestanden
• Bestanden worden redundant opgeslagen
• Mogelijkheid om de bestanden geografisch
redundant op te slaan (Amsterdam - Dublin)
• Je betaald voor transacties én opslag
Tip: Zet bij een blob een goede Cache control header
Tip: Je kan bestanden niet in de root opslaan, maar wel in
een container met de naam “$root”
26. SQL Database (SQL Azure)
• Gelimiteerd in aantal concurrent connecties
• Je betaald voor de grootte van de database
• Microsoft levert availability van de service, geen
(historische) back-up van je data
• Firewall configuratie om rechtstreeks toegang te verlenen
• Goede online tooling voor aanpassing en performance
analyse
Tip: Gebruik SQL Sync om je data te repliceren
Tip: Gebruik DacServices om een back-up van je database te
maken
29. Backup database naar blob storage
CloudBlob backupFile = backupContainer.GetBlobReference(storageName);
// Backup kan alleen naar een lokale file
LocalResource localResource =
RoleEnvironment.GetLocalResource(LocalStorageName);
string filename = localResource.RootPath + backupFile.Name;
DacServices services = new DacServices(connectionString);
services.ExportBacpac(filename, "SeriousRequest");
backupFile.Properties.ContentType = "binary/octet-stream";
backupFile.UploadFile(filename); // Sla de back-up op blob storage
File.Delete(filename); // Ruim de locale file wel weer op!
30. Shared Cache (AppFabric Cache)
• Gedistribueerde cache die overal vandaan te
benaderen is, dus ook buiten je deployment
• Dit in tegenstelling tot de nieuwe cache role
• Gelimiteerd in aantal connecties en grootte
Tip: Connecties moet je disposen!
Tip: Je kan ook data cachen in (JSON) bestanden
op Blob Storage, dit is véél goedkoper
31. Wat zijn voordelen van ontkoppelen?
• Vlak voor het begin van de actie kwam een
verzoek voor 2 nieuwe koppelingen
– UPC
– MyOrder
• Voor elke import was het alleen nodig om
een CSV-regel om te zetten in een bericht op
de queue
32. Wat zijn uitdagingen bij ontkoppelen?
• Hoe garandeer je een unieke sleutel?
• Hoe voorkom je dat worker roles hetzelfde
tegelijkertijd willen uitvoeren?
33. Hoe garandeer je een unieke sleutel?
• Guid.NewGuid() is redelijk uniek
Uitdaging:
“In het financiële systeem heb je maar 5 karakters
aan ruimte voor je unieke sleutel”
• Decimaal zijn dat maar 100.000 unieke waarden
• Base36 levert 365 = 60.466.176 unieke waarden
34. Hoe garandeer je een unieke sleutel?
• Met een queue!
Let op! Berichten op de queue verlopen na
maximaal 7 dagen
Tip: De NuGet package SnowMaker geeft
batches van unieke id’s uit aan nodes en
gebruikt een blob als lockmechanisme
36. Betaalkenmerken genereren
private void AddPaymentIds(CloudQueue cloudQueue)
{
for (int i = 0; i < Threshold; i++)
{
long newId = SnowMaker.NextId("PaymentId");
Alphadecimal paymentId = new Alphadecimal((ulong)newId);
string value = paymentId.ToString("5");
cloudQueue.AddMessage(new CloudQueueMessage(value),
TimeSpan.FromDays(7));
}
}
37. Worker roles niet hetzelfde, tegelijk laten doen
• Je wil de Worker role redundant uitvoeren
voor availability, maar dat betekent ook dat
alle functionaliteit door meerdere servers
tegelijk wordt uitgevoerd
Tip: Zet je staging omgeving uit
Tip: Gebruik een lease op een centrale Blob File
als lock-mechanisme
38. Gebruik lease als lock-mechanisme
CloudBlockContainer lockContainer =
blobClient.GetContainerReference("lock");
CloudBlob lockFile = lockContainer.GetBlobReference("emailLock");
string leaseId = lockFile.AcquireLease(60);
ProcessEmail(lockFile, leaseId);
lockFile.ReleaseLease(leaseId);
42. De flow van een aanvraag
Queue
Betaalkenmerken
Queue
Betaling
Bevestiging Request Confirm
Worker rol
Database
43. De flow van de Rode Kruis beheersite
Database
Worker rol
Cache
Blob storage
44. De flow van de 3FM beheersite
Database
Worker rol
Cache
45. VEEL BEZOEKERS
Hoe voorkom je manipulatie van data?
Hoe kan je dataverkeer beperken?
Hoe kan je meerdere form-factors ondersteunen?
46. Hoe ondersteun je alle browsers?
• Oude browsers kunnen best met HTML5 en
CSS3 overweg zolang we “progressive
enhancement” toepassen
• jQuery zorgt voor een goede abstractie om
tegen de DOM aan te programmeren
• Wel een eigen versie van de jquery.validate
plugin om met IE7 backwards compatibility
mode van Internet Explorer overweg te kunnen
48. Hoe bewaar je state in de client?
• Met een wizard moet je de state meenemen
naar de andere stappen
• Gebruik de MvcSerializer uit MVC Futures
• State kan alleen signed, of encrypted en
signed worden
51. Serialize State (Controller.cs)
[HttpPost, ValidateInput(false)]
public ActionResult Wizard(WizardViewModel updatedModel, string state)
{
ModelState.Clear();
var model = (WizardViewModel)new MvcSerializer().Deserialize(state,
SerializationMode.EncryptedAndSigned);
model.Betaling = updatedModel.Betaling;
if (!TryValidateModel(model.Betaling)) { break; }
return View(model);
}
52. Hoe voorkom je manipulatie van data?
• Serverside validatie is een must
• Clientside validatie is een nice-to-have
• Voorkom cross-site request forgery met een
AntiForgeryToken
Tip: Indien de pagina in een IFrame komt (bijv.
Facebook) is er een extra handeling nodig
55. Anti Forgery (Controller.cs)
[HttpPost, ValidateAntiForgeryToken]
public ActionResult Wizard(WizardViewModel updatedModel, string state)
{
SetP3PCompactPolicy();
return View(model);
}
56. Hoe beveilig je een site met SSL?
• Je wil voorkomen dat persoonlijke gegevens
onderschept kunnen worden
• Je configureert de certificaten in je package in
Visual Studio
• SSL certificaten moet je zelf uploaden, deze
gaan niet mee met je package
Tip: Je moet de hele chain uploaden
58. Hoe kan je dataverkeer optimaliseren?
• Gebruik in je rol IIS 7.5 of 8 voor “gratis” gzip
compressie
• Compressie van JSON is niet standaard
geactiveerd, dit kan je activeren met een startup
task
Tip: Gebruik een CDN voor libraries
Tip: Controleer je site met een tool, bijvoorbeeld
Google PageSpeed Insights
60. EnableCompression.cmd
%windir%system32inetsrvappcmd set config /section:urlCompression
/doDynamicCompression:True /commit:apphost
%windir%system32inetsrvappcmd set config -
section:system.webServer/httpCompression
/+"dynamicTypes.[mimeType='application/json; charset=utf-8',enabled='True']"
/commit:apphost
exit /b 0
61. Hoe kan je meerdere form-factors ondersteunen?
• Met ASP .NET MVC 4 zijn de “DisplayModes”
geïntroduceerd
• De juiste view wordt dynamisch bepaald aan de
hand van condities en de bestandsnaam
• Werkt ook voor partial views
Let op! Er zit een bug in de RTM release, installeer
de “Microsoft.AspNet.Mvc.FixedDisplayModes”
NuGet package
65. DisplayMode (Global.asax.cs)
// Vervang de standaard Mobile DisplayMode
IDisplaymode currentMobileMode = DisplayModeProvider.Instance.Modes
.First(dm => dm.DisplayModeId == DisplayModeProvider.MobileDisplayModeId);
DisplayModeProvider.Instance.Modes.Remove(currentMobileMode);
DisplayModeProvider.Instance.Modes.Insert(0,
new DefaultDisplayMode("Mobile")
{
ContextCondition = MobileCheck
});
66. DisplayMode (Global.asax.cs)
public bool MobileCheck(HttpContextBase context)
{
HttpRequestBase request = context.Request;
if (request.Browser.IsMobileDevice)
{
// Standaard detecteert .NET een tablet ook als een mobile device
bool isTablet = request.UserAgent.Contains("iPad") ||
(request.UserAgent.Contains("Android") && !request.UserAgent.Contains("mobile"));
// Indien de gebruiker op de link “switch naar desktopsite” geklikt heeft
bool forceDesktop = request.QueryString.AllKeys.Contains("mode") &&
request.QueryString["mode"] == "desktop";
return !isTablet && !forceDesktop;
}
return false;
}
68. OPSCHALEN
Welke grootte VM kies je?
Wat moet je weten bij het schalen?
Hoe weet je dat je moet schalen?
Hoeveel servers hadden we nodig?
69. Welke grootte VM kies je?
Extra Small Small Medium
Shared CPU 1 CPU 2 CPU
768 MB 1,75 GB 3,5 GB
20 GB 225 GB 490 GB
5 Mbps 100 Mbps 200 Mbps
€0,015/uur €0,090/uur €0,1790/uur
6x Extra Small 2x Small
70. Wat moet je weten bij het schalen?
• Voor een hogere availability kan je beter meerdere
kleinere VM’s gebruiken
• Je hebt minimaal 2 VM’s nodig voor de 99,95%
garantie
• Je hebt minimaal 3 VM’s nodig voor de 99,95%
garantie als je zelf een update uitrolt
• Updates worden standaard server-voor-server
uitgerold
Tip: Het gaat veel sneller als je alle machines tegelijk
updatet maar doe dit alleen in staging
72. Hoe weet je dat je moet schalen?
• Gebruik de Windows Azure Diagnostics
– Trace Listener
– Performance counters
– IIS Logs
– Event logs
– Crash dumps
• Gebruikt blob en/of table storage
Tip: Gebruik hiervoor een apart storage account
79. Wat heeft de hosting in 2011 gekost?
Compute 598,29
Shared Cache 173,39
SQL Database 10,11
Network (Zone 1) 16,57
Network (Zone 2) 2,91
Storage Capacity 0,10
Storage Transactions 3,97
Totaal €805,34 Totaal €853,10
80. Hoe kunnen we 2011 en 2012 vergelijken?
1 miljoen 45%
Pageviews 2011 Groei 2012
100.000 500
per minuut
Donaties 2011 Piek donaties 2012
€ 5,50
per 1000 donaties
€ 4,10
per 1000 donaties
2011 2012
81. Daarom voor Windows Azure kiezen!
Beschikbaarheid applicaties
Applicaties hebben elkaar niet beïnvloed, geen down time
Dagelijks updates uitgerold
Veel bezoekers op de website
1.500.000+ pageviews
160.000+ donaties verwerkt
Grote toestroom tijdens actie
Makkelijk kunnen opschalen tot 35 servers
Korte levensduur
Lage hosting kosten