Real World Windows Azure

Artikel von Roland Krummenacher im Windows.Developer (6/2014): pdf Real World Windows Azure» als pdf lesen

Mit der Microsoft-Cloud Windows Azure lassen sich hoch skalierbare, weltweit verteilte Anwendungen für Millionen von Endnutzern erstellen. Da aber die wenigsten von uns am nächsten Facebook mitentwickeln, wird Windows Azure im Alltag der Softwareentwicklungsteams selten verwendet. Zu Unrecht, wie sich zeigen wird.

Die Dienste der Azure-Plattform können für jede Art von Software sinnvoll eingesetzt werden – egal, ob es sich um eine Web-, Desktop-, Service- oder Embedded-Applikation handelt. In den fünf Artikeln dieser Serie zeige ich anhand von Beispielen aus meinem Projektalltag, wie Windows Azure in Nicht-Cloud-Applikationen verwendet werden kann. Mein Ziel ist es, dass Sie, liebe Leserin, lieber Leser, die Möglichkeiten der Azure-Plattform auch für Ihr aktuelles Projekt entdecken.

Die einzelnen Artikel dieser Serie sind so aufgebaut, dass ich jeweils ein konkretes Problem vorstelle und eine Lösung dazu aufzeige. Dann werde ich diese Lösung beurteilen und gegebenenfalls ein wiederverwendbares Muster daraus ableiten. Die Serie ist bewusst allgemein gehalten, aber zu jedem Artikel finden Sie in meinem Blog[1] Informationen und Beispiele, wie Sie die Lösung in Ihrem Projekt umsetzen können, sowie die Möglichkeit, mit mir Fragen und Ideen zu diskutieren.

Das Problem

Beim heutigen Problem beschäftigen wir uns mit einer klassischen Client-Server-Architektur, wie sie in Abbildung 1 gezeigt wird. Der Client möchte dem Server Daten senden. Als Schnittstelle zwischen Client und Server kommt bei einem Webclient HTTP, bei einem Desktopclient typischerweise SOAP via WCF oder HTTP via Web-API zum Einsatz. Diese Architektur funktioniert so lange gut, bis der Client auf die Idee kommt, größere Datenmengen an den Server zu senden. Sendet der Client nämlich Anfragen an den Server, die größer als 4 Megabyte sind, erhält er vom Server die Meldung „Maximum request length exceeded“, da die maximale Request-Größe standardmäßig auf 4 Megabyte limitiert ist[2].

Mit einer kurzen Websuche findet man rasch die entsprechende Web.config-Einstellung, um diese Limitierung anzuheben und kann weiterarbeiten. Was bei den praktischen Antworten auf Stack Overflow und Co. jedoch selten beschrieben wird: Diese Limitierung ist durchaus sinnvoll. Zum einen kann es sein, dass der ASP.NET-Worker-Prozess aufgrund technischer Limits nicht mit großen Dateien umgehen kann und dadurch der Webserver plötzlich nicht mehr erreichbar ist. Zum anderen können Denial-of-Service-Attacken einen größeren Schaden anrichten, wenn die maximale Requestgröße erhöht wird[3].

Letztlich läuft es darauf hinaus, dass Webserver für das Empfangen von größeren Datenmengen schlicht nicht geeignet sind. Was ist die Alternative? FTP beispielsweise. FTP-Server sind auf das Empfangen von großen Daten ausgelegt, allerdings hat FTP drei große Nachteile: Es benötigt eine eigene Serverinfrastruktur sowie eine vergleichsweise komplexe Zugriffsverwaltung; außerdem ist FTP schlecht skalierbar. Während die Serverinfrastruktur in der Regel durch die IT bereitgestellt werden kann, ist die Zugriffsverwaltung nicht so einfach. Um als Anbieter die Kontrolle über die Zugriffe der Clients auf den FTP-Server zu behalten, müssen wir für jeden Client umständlich einen eigenen FTP-Account mit Benutzernamen und Passwort anlegen. Die Accounts müssen verwaltet und auch deaktiviert werden, sobald der Client im System gelöscht wurde.

Weiter ist das FTP-Protokoll Session-basiert und damit zustandsbehaftet (stateful), was ein effizientes Load Balancing auf mehrere parallele Server schwierig macht. Eine automatisierte horizontale Skalierung des Backends wird dadurch stark erschwert. Vergleichbare Nachteile haben wir auch, wenn wir beispielsweise SMTP, also E-Mails, zur Übertragung der Daten vom Client zum Server nutzen wollen.

Die Lösung

Um dieses Problem zu lösen, haben wir uns in unserem Projekt den Windows Azure Blob Storage näher angeschaut. Er bietet eine Dateiverwaltung in der Cloud und funktioniert auf den ersten Blick ähnlich wie ein FTP-Server. Im Unterschied zu FTP werden Dateien aber über eine HTTP-REST-Schnittstelle gespeichert, gelesen und verwaltet. Und der Zugriff erfolgt nicht mittels Benutzername und Passwort, sondern mithilfe eines erweiterten und kryptografisch sicheren URL, eines so genannten Shared-Access-Signatur-URL. Dadurch fällt die Verwaltung von Logindaten weg. Abbildung 2 zeigt uns den Vorgang: Zunächst teilt der Client dem Server mit, dass er Daten senden möchte. Der Server antwortet, dass der Client diese Daten auf dem Blob Storage speichern soll, generiert einen SAS-URL und liefert ihn dem Client mit. Der Client lädt nun seine Daten mittels des erhaltenen URL auf den Blob Storage. Dazu könnte er direkt das HTTP-REST-API verwenden.

Abbildung1

Abbildung 1: Wie übertragen wir größere Datenmengen vom Client zum Server?

Abbildung2

Abbildung 2: Zwischenablage der Daten in der Cloud

Komfortabler geht es jedoch mithilfe der Azure Storage Client Library, die für diverse Programmiersprachen verfügbar ist und unter .NET als NuGet-Paket WindowsAzure.Storage eingebunden werden kann. Der Server nutzt dieselbe Library, um den SAS-URL zu generieren (Listing 1). Schließlich teilt der Client dem Server mit, dass die Datei auf den Blob Storage hochgeladen wurde und nun vom Server verarbeitet werden kann.

Beurteilung

Was haben wir mit dieser Lösung gewonnen? Zunächst einmal Sicherheit und Verfügbarkeit. Die Clients können den Server nicht mehr mit großen Datenmengen
„verstopfen“ oder ihn damit sogar in die Knie zwingen. Dadurch bleibt er stets verfügbar und bietet weniger Angriffsmöglichkeiten für DoS-Attacken. Weiter haben wir dank SAS-URLs eine einfache, aber sehr flexible Möglichkeit zur Autorisierung der Clientzugriffe.

abb4

Zudem können Daten vor der Verarbeitung durch den Server verifiziert werden: Ist eine Datei beispielsweise massiv größer als erwartet, kann der Server entscheiden, sie vom Blob Storage zu löschen, ohne dass sie heruntergeladen werden muss. Der Blob Storage bietet weiter die Möglichkeit, Metadaten eines Blobs wie den MD5-Hash oder das letzte Änderungsdatum abzufragen.

Was hat sich an unserer Architektur mit dieser Lösung geändert? Während bislang Daten durch den Server synchron verarbeitet wurden, erfolgt das nun asynchron. Das bedeutet auch, dass der Server entscheiden kann, zu welchem Zeitpunkt er die Daten verarbeiten will. Der Client wartet nicht mehr auf den Server, sondern wird zu einem späteren Zeitpunkt benachrichtigt, sofern er am Resultat interessiert ist. Ob man mit dem Wechsel von der synchronen zur asynchronen Kommunikation leben kann, muss immer für die jeweilige Situation entschieden werden.

Skalierbarkeit

Was ist mit der Skalierbarkeit? Um zu zeigen, dass die Lösung nicht nur die Sicherheit und die Verfügbarkeit des Servers, sondern auch dessen Skalierbarkeit erhöht, muss sie noch etwas erweitert werden (Abb. 3). Während der Webserver noch immer für das Ausstellen der SAS-URLs verantwortlich ist, hat er nun nichts mehr mit der eigentlichen Verarbeitung der Daten zu tun. Der Client lädt die Daten mithilfe des SAS-URL zum Blob Storage hoch und schickt dann eine Nachricht mit den Blob-Daten in eine Warteschlange (Queue).

Abbildung3

Abbildung 3: Skalierbare  Lösung mithilfe von Warteschlangen

Auf Windows Azure steht dafür entweder der Azure Queue Storage oder der Azure Service Bus zur Verfügung. Beide Dienste bieten einen Queueing- Mechanismus als Service an. Der Zugriff funktioniert auch hier mittels SAS-URLs. Die Verarbeitung der Daten erfolgt nun durch mehrere eigene Worker-Prozesse. Diese Worker-Prozesse können auf derselben Maschine wie der Webserver laufen, auf verschiedenen separaten Maschinen oder auch in der Cloud selbst, falls gewünscht.

Die Worker-Prozesse empfangen Nachrichten aus der Queue und verarbeiten die dazugehörenden Daten aus dem Blob-Speicher. Da die Nachricht nur an jeweils einen Prozess ausgeliefert wird, können die Worker-Prozesse die Daten parallel verarbeiten. Dadurch wird das ganze System beliebig skalierbar. Auf meiner GitHub-Seite [5] finden Sie eine Visual Studio Solution, die die Architektur aus Abbildung 3 demonstriert. Der Code wurde bewusst einfach gehalten.

Für eine produktive Implementation sollte als Queueing-System des Windows Azure Service Bus berücksichtigt werden, da er weit mehr Funktionalitäten bietet als die Windows Azure Queues. Zudem muss die Datenverarbeitung fehlertolerant implementiert werden, damit eine Datei nicht doppelt verarbeitet wird.

Webclients und CORS

Die gezeigte Lösung funktioniert für alle Arten von Clients, egal ob man z.B. WPF, WinForms, Java oder eineApp-Technologie verwendet. Auch für browserbasierte Applikationen kann diese Lösung eingesetzt werden. Um mit JavaScript auf den Azure Storage zuzugreifen, wird noch eine Cross-Origin Resource Sharing Policy (CORSPolicy) benötigt, die vorgängig auf dem Storage-Account gesetzt werden muss. Die Details dazu finden Sie unter[4].

Datenschutz und Kosten

Sollten Sie Bedenken bezüglich des Datenschutzes in der Cloud haben, besteht die Möglichkeit, die Daten im Vorfeld zu verschlüsseln. Tauschen Sie dazu zwischen Client und Server neben dem SAS-URL für die Verschlüsselung zusätzlich einen Schlüssel aus. Dieser kann sowohl symmetrisch (z.B. AES) als auch asymmetrisch (z.B. RSA) sein. Es ist sinnvoll, eine Komprimierung der Daten zu erwägen, bevor Sie sie verschlüsseln und hochladen.

Microsofts Windows Azure und Amazons Web Services stehen seit Jahren im Preiskampf miteinander. Dies führte dazu, dass die Preise für den Windows Azure Storage in der Vergangenheit einige Male gesenkt wurden. Zum Zeitpunkt des Verfassens dieses Artikels kostet ein Gigabyte pro Monat 0,053 Euro. Zusätzlich wird pro 100 000 Storage-Zugriffe ein Cent fällig[6]. Für die meisten Applikationen sind diese Kosten vernachlässigbar klein, insbesondere wenn die Daten nur kurz auf der Cloud zwischengespeichert sind. Neben dem Storage bezahlt man auch den Transfer von Daten aus dem Cloud-Datencenter heraus, wobei die ersten fünf Gigabyte pro Monat nichts kosten. Eingehende Datentransfers sind immer kostenlos. Die Kosten für die Azure Queue bzw. den Azure Service Bus finden Sie ebenfalls unter[6].

Fazit

Dieser erste Artikel in der Serie zu Real World Windows Azure zeigt, wie Windows Azure als Zwischenablage genutzt werden kann, falls man größere Datenmengen vom Client zum Server übertragen muss. Der Azure Storage bietet hier eine einfache, sichere und skalierbare Lösung an. Im nächsten Artikel werden wir sehen, wie mithilfe von Windows Azure ein Industrieroboter ferngewartet werden kann.

Links & Literatur
[1] http://rolandkru.azurewebsites.net/rwwa
[2] http://msdn.microsoft.com/en-us/library/system.web.conguration.httpruntimesection.maxrequestlength(v=vs.110).aspx
[3] http://support.microsoft.com/default.aspx?scid=kb;EN-US;295626
[4] http://rolandkru.azurewebsites.net/rwwa1
[5] https://github.com/rolandkru/RWWA-Article1
[6] http://www.windowsazure.com/de-de/pricing/overview/

This entry was posted in Artikel, Storage and tagged , , , , . Bookmark the permalink.

2 Responses to Real World Windows Azure

  1. Pingback: RWWA Artikel 1: Zwischenablage in der Cloud | Roland Krummenacher

  2. Pingback: Real World Windows Azure | Roland Krummenacher

Leave a Reply

Your email address will not be published. Required fields are marked *