17.03.2006, 18:41 Uhr

Mehr Performance für ASP.NET-Anwendungen

Mit ASP.NET lassen sich von Hause aus Webapplikationen bauen, die deutlich besser skalieren und performanter ausgeführt werden als klassische ASP-Applikationen. Um das Potenzial von ASP.NET noch besser auszureizen, sollte man einige Aspekte bei der Architektur und Entwicklung beachten.
Golo Haas beschäftigt sich seit 2001 mit .NET und leitet die Microsoft-Communities myCSHARP.de und guide to C#.
Microsoft hat es mit ASP.NET sehr einfach gemacht, leistungsfähige Webapplikationen zu entwickeln. Allerdings vermitteln ASP.NET und insbesondere Visual Studio den Eindruck, dass sich mit einigen Mausklicks all das erreichen liesse, was früher händisch umgesetzt werden musste. Dies ist allerdings gerade im Hinblick auf Skalierbarkeit und Performance oft nicht richtig, da hier durch ein wenig Handarbeit noch viel erreicht werden kann. Prinzipiell lassen sich die Techniken, mit denen die Skalierbarkeit und die Performance von Webapplikationen verbessert werden können, in vier Kategorien einteilen: Das Volumen der übertragenen Daten zu minimieren, den serverseitigen Zugriff auf die Daten zu beschleunigen, sonstige Aufgaben auf dem Server in den Hintergrund zu verlagern und schliesslich die Ausführungsumgebung zu verbessern.

Datenvolumen minimieren

Ein wesentliches Merkmal von Webapplikationen ist das Request-Response-Prinzip, also die Tatsache, dass die Darstellung auf dem Client verbindungslos stattfindet, für jede Anfrage allerdings eine Verbindung zum Server aufgenommen werden muss. Da dieser Verbindungsaufbau und die damit einhergehende Datenübertragung der grösste Flaschenhals bei Webapplikationen ist, liegt es auf der Hand, dies möglichst zu vermeiden und das Datenvolumen zu minimieren, wenn sich eine Verbindung nicht vermeiden lässt. Um Postbacks weitgehend zu vermeiden, bieten sich zwei Techniken an - Javascript und Ajax. Durch den Einsatz von Javascript wird es möglich, Logik vom Server auf den Client zu verlagern, beispielsweise die Validierung von Eingabefeldern bereits auf dem Client auszuführen, und die Daten nur dann an den Server zu senden, wenn die Validierung auf dem Client bereits erfolgreich durchgeführt werden konnte. Ajax hingegen steht für Asynchronous Javascript and XML und bezeichnet das Nachladen einzelner Webseitenbereiche per Javascript. So können einzelne Bereiche je nach Bedarf per Javascript von einem Webservice über XML nachgeladen werden und es muss nicht in jedem Fall die vollständige Seite geladen werden (siehe dazu auch Artikel auf Seite 48). Sofern sich vollständige Postbacks zum Server nicht vermeiden lassen, sollte deren Datenvolumen aber so gering wie möglich ausfallen. In ASP.NET ist standardmässig der sogenannte Viewstate aktiviert, in dem eingegebene Daten und geladene Werte von Controls zwischengespeichert werden. Diese Daten werden bei jedem Postback aber mit der eigentlichen Anfrage an den Server gesendet und nachher auch wieder mit ausgeliefert. Sofern diese Funktion also nicht zwingend benötigt wird, lässt sich durch Abschalten des Viewstates die übertragene Datenmenge reduzieren. Der Viewstate lässt sich mit dem Kommando <%@ Page EnableViewState="false" %> für eine ganze Seite ausschalten. Über das Enableview-State-Property kann der Viewstate auch für ein einzelnes Control deaktiviert werden. Neben möglichst wenigen Postbacks und dem Abschalten des Viewstates gilt zudem noch, dass in Webapplikationen generell nur so viele Daten geladen werden sollten, wie nötig. Dies gilt insbesondere, wenn Listen oder Tabellen von Daten dargestellt werden sollen. Anstatt hier alle Datensätze auf einmal zu laden, sollte man auf Paging zurückgreifen, was von den entsprechenden Steuerelementen in ASP.NET 2.0 von Haus aus unterstützt wird. Auch dadurch lässt sich das übertragene Datenvolumen gehörig senken [2].

Serverseitiger Datenzugriff

Neben der Übertragung der Daten vom Server zum Client und umgekehrt spielt es in Webapplikationen auch eine grosse Rolle, wie schnell die Daten vom Server aus den jeweiligen Datenquellen abgefragt werden können - sei es aus einer Datenbank, einer XML-Datei oder einer sonstigen Quelle. Für Datenbanken empfiehlt es sich, auf das sogenannte Connection Pooling zurückzugreifen. Anstatt für jede Datenbankverbindung eine neue, eigene Verbindung zu öffnen, wird beim Connection Pooling eine feste Anzahl geöffneter Verbindungen vorgehalten, die dann nur noch zugewiesen werden. Schliesst der Server eine Verbindung, wird diese nicht wirklich geschlossen, sondern nur wieder in den Pool zurück- und damit freigegeben. In ADO.NET ist Connection Pooling für den SQL Server automatisch aktiviert, sofern bei jeder Anfrage der gleiche Connectionstring verwendet wird [3]. (siehe Grafik)
Ein weiterer Aspekt, wie Datenbankabfragen beschleunigt werden können, ist der Einsatz von Stored Procedures. Anstatt die SQL-Anweisungen zur Laufzeit an die Datenbank zu senden, die dort dann kompiliert und schliesslich ausgeführt werden, legt man die SQL-Anweisungen vorkompiliert in der Datenbank ab und ruft sie dort nur noch auf, was bedeutend schneller vonstatten geht. Zudem gilt - unabhängig, ob die Daten aus einer Datenbank oder einer anderen Datenquelle gelesen werden - dass Zugriffe auf externe Resourcen möglichst selten stattfinden sollten. Um die Häufigkeit zu verringern, lässt sich an dieser Stelle Caching einsetzen, das vom Cachen einzelner Datensätze über das Cachen kompletter Tabellen oder Dateien bis hin zum Cachen ganzer Webseiten reichen kann. Die Caching-Klassen und -Attribute in ASP.NET sind hierzu äusserst hilfreich [1].

Weitere Serveraufgaben

Neben dem Datenzugriff gibt es zahlreiche weitere Serveraufgaben, welche die Leistung einer Webapplikation negativ beeinflussen können. Ein klassisches Beispiel ist der Versand von E-Mails, was bei einer grösseren Anzahl von E-Mails durchaus sehr langsam werden kann und somit die Ausführung der ganzen Applikation verzögert. Für solche Szenarien gibt es im Wesentlichen zwei Lösungsansätze. Zum einen kann man auf mehrere Threads zurückgreifen, das heisst, dass für die zeitaufwändige Aufgabe ein eigener Thread gestartet wird, der im Hintergrund asynchron arbeitet und den Vordergrundthread nicht aufhält. So können beispielsweise E-Mails sehr schnell versendet werden, da die im Vordergrund laufende Applikation nur noch den Auftrag abgibt, eine E-Mail zu versenden, aber nicht mehr auf das Ende dieses Auftrages warten muss. Der zweite Ansatz ist das sogenannte Batching, also das Zusammenfassen von einzelnen Aufgaben zu einzelnen Tasks in einer grossen Aufgabe. Statt eine Menge von E-Mails jeweils einzeln zu versenden, werden die E-Mails zunächst gesammelt und dann auf einen Schlag gemeinsam versendet. Dadurch wird nur einmalig eine höhere Last erzeugt und die Webapplikation hat ansonsten ihre volle Leistung. Zudem lässt sich dieser Batchjob durch einen Hintergrundthread komplett von der eigentlichen Applikation trennen, so dass man hier sehr viel Performance gewinnen kann.

Ausführungsumgebung

Schliesslich lässt sich neben all diesen Techniken, die direkt die Applikation betreffen, auch die Ausführungsumgebung der Applikation modifizieren, um eine höhere Leistung zu bieten. An erster Stelle steht hier das Kernel-Mode-Caching des IIS 6.0, was allein schon seinen Einsatz gegenüber den Versionen 5.x rechtfertigt [4]. Beim Kernel-Mode-Caching hält der IIS die auszuliefernden Webseiten in einem Cache vor, der von einem im Kernel-Modus laufenden Treiber abgefragt wird. Erhält der IIS also eine Anfrage nach einer bestimmten Webseite, die sich bereits in diesem Cache befindet, so muss nicht nur ASP.NET nicht anspringen, sondern es muss nicht einmal auf den Kontext des IIS-Benutzerkontos umgeschaltet werden - der im Kernel-Modus laufende Treiber liefert die Seite direkt zurück.

Skalierbarer und performanter

Alles in allem lässt sich aus einer in ASP.NET geschriebenen Webapplikation noch deutlich mehr herausholen, als ASP.NET und Visual Studio zunächst vermitteln. Da sich alle beschriebenen Techniken sehr einfach umsetzen lassen, lohnt sich ihr Einsatz auf alle Fälle, um Webapplikationen besser skalierbar und performanter zu machen.
Golo Haas


Das könnte Sie auch interessieren