Freigeben über


Bewährte Methoden für die Webentwicklung (Erstellen Real-World Cloud-Apps mit Azure)

von Rick Anderson, Tom Dykstra

Download Fix It Project oder Download E-Book

Das E-Book Building Real World Cloud Apps with Azure basiert auf einer Präsentation, die von Scott Guthrie entwickelt wurde. Es werden 13 Muster und Methoden erläutert, die Ihnen bei der erfolgreichen Entwicklung von Web-Apps für die Cloud helfen können. Informationen zum E-Book finden Sie im ersten Kapitel.

Bei den ersten drei Mustern ging es um den Aufbau eines agilen Entwicklungsprozesses; der Rest geht um Architektur und Code. Dies ist eine Sammlung von bewährten Methoden für die Webentwicklung:

Diese Methoden gelten für die gesamte Webentwicklung, nicht nur für Cloud-Apps, aber sie sind besonders wichtig für Cloud-Apps. Sie arbeiten zusammen, um Sie dabei zu unterstützen, die hochflexible Skalierung der Cloudumgebung optimal zu nutzen. Wenn Sie diese Methoden nicht befolgen, treten beim Skalieren Ihrer Anwendung Einschränkungen auf.

Zustandslose Webebene hinter einem intelligenten Lastenausgleich

Die zustandslose Webebene bedeutet, dass Sie keine Anwendungsdaten im Webserverspeicher oder Dateisystem speichern. Wenn Sie Ihre Webebene zustandslos halten, können Sie sowohl eine bessere Kundenerfahrung bieten als auch Geld sparen:

  • Wenn die Webebene zustandslos ist und sich hinter einem Lastenausgleich befindet, können Sie schnell auf Änderungen im Anwendungsdatenverkehr reagieren, indem Sie Server dynamisch hinzufügen oder entfernen. In der Cloudumgebung, in der Sie nur für Serverressourcen bezahlen, solange Sie sie tatsächlich verwenden, kann diese Möglichkeit, auf Änderungen der Nachfrage zu reagieren, zu enormen Einsparungen führen.
  • Eine zustandslose Webebene ist architektonisch viel einfacher, um die Anwendung hochskalieren zu können. Auch dies ermöglicht es Ihnen, schneller auf Skalierungsanforderungen zu reagieren und weniger Geld für Die Entwicklung und Tests im Prozess auszugeben.
  • Cloudserver wie lokale Server müssen gelegentlich gepatcht und neu gestartet werden. Und wenn die Webebene zustandslos ist, führt das erneute Weiterleiten von Datenverkehr, wenn ein Server vorübergehend ausfällt, keine Fehler oder unerwartetes Verhalten.

Die meisten realen Anwendungen müssen den Zustand für eine Websitzung speichern. der Standard Punkt hier nicht darin besteht, es auf dem Webserver zu speichern. Sie können den Zustand auf andere Weise speichern, z. B. auf dem Client in Cookies oder serverseitig außerhalb des Prozesses in ASP.NET Sitzungszustand mithilfe eines Cacheanbieters. Sie können Dateien in Windows Azure Blob Storage anstelle des lokalen Dateisystems speichern.

Ein Beispiel dafür, wie einfach es ist, eine Anwendung in Windows Azure-Websites zu skalieren, wenn Ihre Webebene zustandslos ist, finden Sie auf der Registerkarte Skalieren für eine Windows Azure-Website im Verwaltungsportal:

Registerkarte

Wenn Sie Webserver hinzufügen möchten, können Sie einfach den Schieberegler instance Anzahl nach rechts ziehen. Legen Sie es auf 5 fest, und klicken Sie auf Speichern. Innerhalb von Sekunden haben Sie fünf Webserver in Windows Azure, die den Datenverkehr Ihrer Website verarbeiten.

Fünf Instanzen

Sie können die anzahl der instance genauso einfach auf 3 oder wieder auf 1 festlegen. Wenn Sie eine Rückskalierung durchführen, sparen Sie sofort Geld, da Windows Azure nach Minuten und nicht nach Stunde berechnet.

Sie können Windows Azure auch anweisen, die Anzahl von Webservern basierend auf der CPU-Auslastung automatisch zu erhöhen oder zu verringern. Wenn die CPU-Auslastung im folgenden Beispiel unter 60 % liegt, verringert sich die Anzahl der Webserver auf mindestens 2, und wenn die CPU-Auslastung über 80 % liegt, wird die Anzahl der Webserver auf maximal 4 erhöht.

Skalieren nach CPU-Auslastung

Oder was, wenn Sie wissen, dass Ihre Website nur während der Arbeitszeit ausgelastet ist? Sie können Windows Azure anweisen, mehrere Server tagsüber auszuführen und abends, nachts und am Wochenende auf einen einzelnen Server zu reduzieren. Die folgende Reihe von Screenshots zeigt, wie Sie die Website so einrichten, dass ein Server außerhalb der Geschäftszeiten und 4 Server während der Arbeitszeit von 8:00 bis 17:00 Uhr ausgeführt wird.

Skalieren nach Zeitplan

Festlegen von Zeitplanzeiten

Tageszeitplan

Wochenwochenzeitplan

Zeitplan für Wochenenden

All dies kann natürlich sowohl in Skripts als auch im Portal erfolgen.

Die Möglichkeit ihrer Anwendung, horizontal hochzuskalieren, ist in Windows Azure nahezu unbegrenzt, solange Sie Hindernisse beim dynamischen Hinzufügen oder Entfernen von Server-VMs vermeiden, indem Sie die Webebene zustandslos halten.

Vermeiden des Sitzungszustands

Im praktischen Einsatz von Cloud-Apps lässt sich das Speichern von Zustandsinformationen für eine Benutzersitzung oft nicht vermeiden. Allerdings beeinträchtigen einige Herangehensweisen die Leistung und Skalierbarkeit stärker als andere. Wenn Sie einen Sitzungszustand speichern müssen, ist es am besten, die Menge der Zustandsinformationen niedrig zu halten und sie in Cookies zu speichern. Wenn dies nicht möglich ist, besteht die nächstbeste Lösung darin, ASP.NET Sitzungszustand mit einem Anbieter für verteilten In-Memory-Cache zu verwenden. Die schlechteste Lösung im Hinblick auf Leistung und Skalierbarkeit wäre es, einen datenbankbasierten Sitzungszustandsanbieter zu verwenden.

Verwenden eines CDN zum Zwischenspeichern statischer Dateiressourcen

CDN ist ein Akronym für Content Delivery Network. Sie stellen statische Dateiressourcen wie Bilder und Skriptdateien für einen CDN-Anbieter bereit, und der Anbieter speichert diese Dateien in Rechenzentren auf der ganzen Welt zwischen, sodass sie überall dort, wo Personen auf Ihre Anwendung zugreifen, relativ schnelle Antworten und geringe Latenz für die zwischengespeicherten Ressourcen erhalten. Dies beschleunigt die Gesamtladezeit der Website und reduziert die Last auf Ihren Webservern. CDNs sind besonders wichtig, wenn Sie ein Publikum erreichen, das geografisch weit verbreitet ist.

Windows Azure verfügt über ein CDN, und Sie können andere CDNs in einer Anwendung verwenden, die in Windows Azure oder einer beliebigen Webhostingumgebung ausgeführt wird.

Verwenden der asynchronen Unterstützung von .NET 4.5, um zu verhindern, dass Aufrufe blockiert werden

.NET 4.5 hat die Programmiersprachen C# und VB verbessert, um die asynchrone Verarbeitung von Aufgaben erheblich zu vereinfachen. Der Vorteil der asynchronen Programmierung ist nicht nur für Parallelverarbeitungssituationen, z. B. wenn Sie mehrere Webdienstaufrufe gleichzeitig starten möchten. Außerdem ermöglicht es Ihrem Webserver, bei hohen Auslastungsbedingungen effizienter und zuverlässiger zu arbeiten. Ein Webserver verfügt nur über eine begrenzte Anzahl von Threads, und bei hohen Auslastungsbedingungen, wenn alle Threads verwendet werden, müssen eingehende Anforderungen warten, bis Threads freigegeben sind. Wenn Ihr Anwendungscode Aufgaben wie Datenbankabfragen und Webdienstaufrufe nicht asynchron verarbeitet, werden viele Threads unnötig gebunden, während der Server auf eine E/A-Antwort wartet. Dadurch wird der Datenverkehr begrenzt, den der Server bei hoher Auslastung verarbeiten kann. Bei der asynchronen Programmierung werden Threads, die darauf warten, dass ein Webdienst oder eine Datenbank Daten zurückgibt, für neue Anforderungen freigegeben, bis die Daten empfangen werden. Auf einem ausgelasteten Webserver können dann Hunderte oder Tausende von Anforderungen sofort verarbeitet werden, die andernfalls auf die Freigabe von Threads warten würden.

Wie Sie bereits gesehen haben, ist es genauso einfach, die Anzahl der Webserver, die Ihre Website behandeln, zu verringern, als sie zu erhöhen. Wenn ein Server also einen höheren Durchsatz erzielen kann, benötigen Sie nicht so viele davon, und Sie können Ihre Kosten senken, da Sie weniger Server für ein bestimmtes Datenverkehrsvolumen benötigen als andernfalls.

Unterstützung für das asynchrone Programmiermodell von .NET 4.5 ist in ASP.NET 4.5 für Web Forms, MVC und Web-API, in Entity Framework 6 und in der Windows Azure Storage-API enthalten.

Async-Unterstützung in ASP.NET 4.5

In ASP.NET 4.5 wurde nicht nur der Sprache, sondern auch den MVC-, Web Forms- und Web-API-Frameworks Unterstützung für die asynchrone Programmierung hinzugefügt. Beispielsweise empfängt eine ASP.NET MVC-Controlleraktionsmethode Daten aus einer Webanforderung und übergibt die Daten an eine Ansicht, die dann den HTML-Code erstellt, der an den Browser gesendet werden soll. Häufig muss die Aktionsmethode Daten aus einer Datenbank oder einem Webdienst abrufen, um sie auf einer Webseite anzuzeigen oder die in einer Webseite eingegebenen Daten zu speichern. In diesen Szenarien ist es einfach, die Aktionsmethode asynchron zu gestalten: Anstatt ein ActionResult-Objekt zurückzugeben, geben Sie Task<ActionResult> zurück und markieren die Methode mit dem asynchronen Schlüsselwort (keyword). Wenn in der -Methode eine Codezeile einen Vorgang startet, der wartezeiten erfordert, markieren Sie sie mit der Schlüsselwort (keyword) await.

Hier sehen Sie eine einfache Aktionsmethode, die eine Repositorymethode für eine Datenbankabfrage aufruft:

public ActionResult Index()
{
    string currentUser = User.Identity.Name;
    var result = fixItRepository.FindOpenTasksByOwner(currentUser);

    return View(result);
}

Und hier ist die gleiche Methode, die den Datenbankaufruf asynchron verarbeitet:

public async Task<ActionResult> Index()
{
    string currentUser = User.Identity.Name;
    var result = await fixItRepository.FindOpenTasksByOwnerAsync(currentUser);

    return View(result);
}

Unter dem Cover generiert der Compiler den entsprechenden asynchronen Code. Wenn die Anwendung aufruft FindTaskByIdAsync, stellt ASP.NET die FindTask Anforderung, entlädt dann den Workerthread und stellt ihn zur Verarbeitung einer anderen Anforderung zur Verfügung. Wenn die FindTask Anforderung abgeschlossen ist, wird ein Thread neu gestartet, um die Verarbeitung des codes fortzusetzen, der nach diesem Aufruf eingeht. Während der Zwischenzeit zwischen dem Zeitpunkt, an dem die FindTask Anforderung initiiert wird, und der Rückgabe der Daten steht Ihnen ein Thread zur Verfügung, um nützliche Aufgaben zu erledigen, die andernfalls gebunden wären, um auf die Antwort zu warten.

Es gibt einen gewissen Mehraufwand für asynchronen Code, aber unter Bedingungen mit niedriger Last ist dieser Mehraufwand vernachlässigbar, während Sie unter Bedingungen mit hoher Auslastung Anforderungen verarbeiten können, die andernfalls auf verfügbare Threads warten würden.

Diese Art der asynchronen Programmierung ist seit ASP.NET 1.1 möglich, aber es war schwierig zu schreiben, fehleranfällig und schwierig zu debuggen. Nachdem wir nun die Codierung dafür in ASP.NET 4.5 vereinfacht haben, gibt es keinen Grund mehr, dies nicht mehr zu tun.

Async-Unterstützung in Entity Framework 6

Im Rahmen der asynchronen Unterstützung in Version 4.5 haben wir asynchrone Unterstützung für Webdienstaufrufe, Sockets und Dateisystem-E/A bereitgestellt, aber das häufigste Muster für Webanwendungen besteht darin, eine Datenbank zu treffen, und unsere Datenbibliotheken haben keine asynchrone Unterstützung. Entity Framework 6 fügt jetzt asynchrone Unterstützung für den Datenbankzugriff hinzu.

In Entity Framework 6 verfügen alle Methoden, die dazu führen, dass eine Abfrage oder ein Befehl an die Datenbank gesendet wird, asynchrone Versionen. Das hier gezeigte Beispiel zeigt die asynchrone Version der Find-Methode .

public async Task<FixItTask> FindTaskByIdAsync(int id)
{
    FixItTask fixItTask = null;
    Stopwatch timespan = Stopwatch.StartNew();

    try
    {
        fixItTask = await db.FixItTasks.FindAsync(id);
        
        timespan.Stop();
        log.TraceApi("SQL Database", "FixItTaskRepository.FindTaskByIdAsync", timespan.Elapsed, "id={0}", id);
    }
    catch(Exception e)
    {
        log.Error(e, "Error in FixItTaskRepository.FindTaskByIdAsynx(id={0})", id);
    }

    return fixItTask;
}

Und diese asynchrone Unterstützung funktioniert nicht nur für Einfügungen, Löschvorgänge, Updates und einfache Suchen, sie funktioniert auch mit LINQ-Abfragen:

public async Task<List<FixItTask>> FindOpenTasksByOwnerAsync(string userName)
{
    Stopwatch timespan = Stopwatch.StartNew();

    try
    {
        var result = await db.FixItTasks
            .Where(t => t.Owner == userName)
            .Where(t=>t.IsDone == false)
            .OrderByDescending(t => t.FixItTaskId).ToListAsync();

        timespan.Stop();
        log.TraceApi("SQL Database", "FixItTaskRepository.FindTasksByOwnerAsync", timespan.Elapsed, "username={0}", userName);

        return result;
    }
    catch (Exception e)
    {
        log.Error(e, "Error in FixItTaskRepository.FindTasksByOwnerAsync(userName={0})", userName);
        return null;
    }
}

Es gibt eine Async Version der ToList -Methode, da in diesem Code die Methode ist, die bewirkt, dass eine Abfrage an die Datenbank gesendet wird. Die Where Methoden und OrderByDescending konfigurieren nur die Abfrage, während die ToListAsync -Methode die Abfrage ausführt und die Antwort in der result Variablen speichert.

Zusammenfassung

Sie können die hier beschriebenen bewährten Methoden für die Webentwicklung in jedem Webprogrammierungsframework und jeder Cloudumgebung implementieren, aber wir verfügen über Tools in ASP.NET und Windows Azure, um dies zu vereinfachen. Wenn Sie diesen Mustern folgen, können Sie Ihre Webebene problemlos aufskalieren, und Sie minimieren Ihre Ausgaben, da jeder Server mehr Datenverkehr verarbeiten kann.

Im nächsten Kapitel wird erläutert, wie die Cloud Szenarien für einmaliges Anmelden ermöglicht.

Ressourcen

Weitere Informationen finden Sie in den folgenden Ressourcen.

Zustandslose Webserver:

CDN:

Asynchrone Programmierung:

Weitere bewährte Methoden für die Webentwicklung finden Sie in den folgenden Ressourcen: