ASP Tipp 1: Zwischenspeichern Sie häufig verwendete Daten auf dem Webserver

Eine typische ASP-Seite ruft Daten aus einem Back-End-Datenspeicher ab und zeichnet die Ergebnisse dann in HTML (Hypertext Markup Language). Unabhängig von der Geschwindigkeit Ihrer Datenbank ist das Abrufen von Daten aus dem Speicher wesentlich schneller als aus dem Back-End-Datenspeicher. Das Lesen der Daten von einer lokalen Festplatte ist normalerweise ebenfalls schneller als das Abrufen aus einer Datenbank. Aus diesem Grund können Sie die Leistung in der Regel verbessern, indem Sie die Daten auf dem Webserver, entweder im Arbeitsspeicher oder auf der Festplatte, zwischenspeichern.

Beim Zwischenspeichern handelt es sich um einen klassischen Kompromiss zwischen Platz und Zeit. Wenn Sie die richtigen Informationen zwischenspeichern, können Sie beeindruckende Leistungssteigerungen erzielen. Damit ein Cache effektiv ist, muss er Daten enthalten, die häufig wieder verwendet werden. Außerdem muss die Neuberechnung dieser Daten (relativ) teuer sein. Ein Cache voller unnötiger Daten ist eine Speicherverschwendung.

Daten, die sich nicht oft ändern, bieten sich zum Zwischenspeichern an, denn Sie müssen sich keine Gedanken darüber machen, die Daten im Laufe der Zeit mit der Datenbank zu synchronisieren. Kombinationsfeldlisten, Referenztabellen, DHTML-Fetzen, XML-Zeichenfolgen (Extensible Markup Language), Menüoptionen und Sitekonfigurationsvariablen (einschließlich Datenquellennamen (DNS) IP-Adressen (Internet Protocol) und Web Pfade) sind für das Zwischenspeichern geeignet. Beachten Sie, dass es möglich ist, die Präsentation der Daten statt die Daten selbst zwischen zu speichern. Wenn sich eine ASP-Seite häufig ändert und ihre Zwischenspeicherung kostspielig ist (z. B. ihr gesamter Produktkatalog), sollten Sie eine HTML-Voraberstellung in Erwägung ziehen, anstatt sie bei jeder Anforderung neu zu zeichnen.

Wo sollen Daten zwischengespeichert werden? Welche Strategien sollten beim Zwischenspeichern befolgt werden? Daten werden häufig entweder im Arbeitsspeicher oder auf den Festplatten des Webservers zwischengespeichert. Diese Optionen werden in den nächsten beiden Tipps behandelt.

ASP Tipp 2: Zwischenspeichern Sie häufig verwendete Daten in den Objekten „Application“ oder „Session“

Das Application- und Session-Objekt in ASP stellen praktische Container zum Zwischenspeichern von Daten im Arbeitsspeicher bereit. Sie können Daten sowohl dem Application- als auch dem Session-Objekt zuweisen. Diese Daten verbleiben zwischen HTTP-Aufrufen im Arbeitsspeicher. Sitzungsdaten werden auf Benutzerbasis gespeichert, während die Anwendungsdaten für alle Benutzer freigegeben werden.

Wann werden die Daten in die Anwendung oder Sitzung geladen? Die Daten werden häufig beim Starten einer Anwendung oder Sitzung geladen. Um Daten beim Anwendungs- oder Sitzungsstart zu laden, fügen Sie Application_OnStart() oder Session_OnStart(), den jeweils geeigneten Code hinzu. Diese Funktionen müssen sich in der Datei Global.asa befinden. Ist dies nicht der Fall, können Sie sie hinzufügen. Sie können die Daten auch erst laden, wenn sie zum ersten Mal benötigt werden. Fügen Sie Ihrer ASP-Seite zu diesem Zweck Code hinzu, der prüft, ob die Daten vorhanden sind, und sie lädt, wenn dies nicht der Fall ist (oder schreiben Sie eine entsprechende wiederverwendbare Skriptfunktion). Dies ist ein Beispiel der klassischen Leistungsmethode, die als verzögerte Auswertung bezeichnet wird. Bei dieser wird eine Berechnung erst bei Bedarf durchgeführt. Dazu ein Beispiel:

<%

Function GetEmploymentStatusList

Dim d

d = Application(„EmploymentStatusList“)

If d = „„ Then

‚ FetchEmploymentStatusList function (not shown)

‚ fetches data from DB, returns an Array

d = FetchEmploymentStatusList()

Application(„EmploymentStatusList“) = d

End If

GetEmploymentStatusList = d

End Function

%>

Sie können ähnliche Funktionen für jeden benötigten Datenblock schreiben.

In welcher Form sollten die Daten gespeichert werden? Sie können alle Variantentypen speichern, da es sich bei allen Skriptvariablen um Varianten handelt. Sie können z. B. Zeichenfolgen, Ganzzahlen oder Arrays speichern. Sie werden häufig den Inhalt eines ADO-Recordsets in einem dieser Variablentypen speichern. Um Daten aus einem ADO-Recordset zu entnehmen, müssen Sie die Daten manuell Feld für Feld in VBScript-Variablen kopieren. Dies ist mithilfe einer der Beständigkeitsfunktionen für ADO-Recordsets, GetRows(), GetString() oder Save() (ADO 2.5), schneller und einfacher. Ausführliche Einzelheiten hierzu gehen über den Zweck dieses Artikels hinaus, aber im Folgenden sehen Sie eine Funktion, die die Verwendung von GetRows() zum Zurückgeben eines Arrays von Recordsetdaten demonstriert.

‚ Get Recordset, return as an Array

Function FetchEmploymentStatusList

Dim rs

Set rs = CreateObject(“ADODB.Recordset”)

rs.Open “select StatusName, StatusID from EmployeeStatus”, _

“dsn=employees;uid=sa;pwd=;”

FetchEmploymentStatusList = rs.GetRows() ‚ Return data as an Array

rs.Close

Set rs = Nothing

End Function

Die oben dargestellte Funktion könnte durch Zwischenspeichern des HTML-Inhalts dieser Liste statt des Arrays weiter angepasst werden. Dazu ein einfaches Beispiel:

‚ Get Recordset, return as HTML Option list

Function FetchEmploymentStatusList

Dim rs, fldName, s

Set rs = CreateObject(“ADODB.Recordset”)

rs.Open “select StatusName, StatusID from EmployeeStatus”, _

“dsn=employees;uid=sa;pwd=;”

s = “<select name=””EmploymentStatus””>” & vbCrLf

Set fldName = rs.Fields(“StatusName“) ‚ ADO Field Binding

Do Until rs.EOF

‚ Next line violates Don’t Do String Concats,

‚ but it’s OK because we are building a cache

s = s & „ <option>„ & fldName & „</option>„ & vbCrLf

rs.MoveNext

Loop

s = s & „</select>„ & vbCrLf

rs.Close

Set rs = Nothing ‚ See Release Early

FetchEmploymentStatusList = s ‚ Return data as a String

End Function

Unter den richtigen Umständen können Sie ADO-Recordsets selbst im Gültigkeitsbereich des Application- oder Session-Objekts zwischenspeichern. Dabei sind aber zwei Dinge zu beachten:

  1. ADO muss als Freethread-Komponente markiert sein.
  2. Sie müssen einen abgetrennten Recordset verwenden.

Wenn es keine Garantie dafür gibt, dass diese beiden Anforderungen erfüllt sind, sollten Sie ADO-Recordsets nicht zwischenspeichern. Im Tipp zu nicht beweglichen Komponenten und im Tipp weiter unten, in dem vom Zwischenspeichern von Datenbankverbindungen abgeraten wird, werden die Risiken beim Speichern von COM-Objekten im Gültigkeitsbereich eines Application- oder Session-Objekts behandelt.

Beim Speichern von Daten im Gültigkeitsbereich eines Application- oder Session-Objekts verbleiben die Daten in diesem, bis Sie sie durch Programmieren ändern, die Sitzung abläuft oder die Webanwendung neu gestartet wird. Was geschieht, wenn die Daten aktualisiert werden müssen? Um eine Aktualisierung von Anwendungsdaten manuell zu erzwingen, rufen Sie eine ASP-Seite auf, auf die nur der Administrator Zugriff hat, und die die Daten aktualisiert. Sie können Ihre Daten stattdessen auch in regelmäßigen Abständen mithilfe einer Funktion aktualisieren. Das folgende Beispiel speichert einen Zeitstempel mit den zwischengespeicherten Daten und aktualisiert die Daten nach einem bestimmten Zeitraum.

<%

‚ error handing not shown…

Const UPDATE_INTERVAL = 300 ‚ Refresh interval, in seconds

‚ Function to return the employment status list

Function GetEmploymentStatusList

UpdateEmploymentStatus

GetEmploymentStatusList = Application(„EmploymentStatusList“)

End Function

‚ Periodically update the cached data

Sub UpdateEmploymentStatusList

Dim d, strLastUpdate

strLastUpdate = Application(„LastUpdate“)

If (strLastUpdate = „„) Or _

(UPDATE_INTERVAL < DateDiff(„s“, strLastUpdate, Now)) Then

‚ Anmerkung: Hier können zwei oder mehr Aufrufe eingehen. Das ist in Ordnung und führt

‚ lediglich zu einigen unnötigen Abrufen (dies kann umgangen werden)

‚ FetchEmploymentStatusList function (not shown)

‚ fetches data from DB, returns an Array

d = FetchEmploymentStatusList()

‚ Update the Application object. Use Application.Lock()

‚ to ensure consistent data

Application.Lock

Application(„EmploymentStatusList“) = Events

Application(„LastUpdate“) = CStr(Now)

Application.Unlock

End If

End Sub

Ein weiteres Beispiel finden Sie im Artikel „World’s Fastest ListBox with Application Data“.

Beachten Sie, dass vom Zwischenspeichern von großen Arrays in Session- oder Application-Objekten abgeraten wird. Bevor Sie auf ein Element des Arrays zugreifen können, setzt die Semantik der Skripterstellungssprachen voraus, dass das gesamte Array kopiert wird. Wenn Sie z. B. ein aus 100.000 Elementen bestehendes Zeichenfolgenarray, das US-amerikanische Postleitzahlen lokalen Wetterstationen zuordnet, in einem Application-Objekt zwischenspeichern, muss ASP zuerst alle 100.000 Wetterstationen in ein temporäres Array kopieren, bevor Sie auch nur eine Zeichenfolge extrahieren können. In diesem Fall empfiehlt es sich, zum Speichern der Wetterstationen eine benutzerdefinierte Komponente mit einer benutzerdefinierten Methode zu erstellen oder eine der Wörterbuchkomponenten zu verwenden.

Zum Schluss noch ein weiterer Kommentar nach dem Motto „das Kind mit dem Badewasser ausschütten“. Arrays stellen schnelle Suche und Speicherung von zentralen Datenpaaren bereit, die im Arbeitsspeicher zusammenhängen. Das Indizieren eines Wörterbuches ist langsamer als das Indizieren eines Arrays. Sie sollten sich für die Datenstruktur entscheiden, die unter den gegebenen Umständen die beste Leistung bietet.

ASP Tipp 3: Zwischenspeichern Sie Daten und HTML auf den Festplatten des Webservers

In einigen Fällen liegen zu viele Daten für die Zwischenspeicherung im Arbeitsspeicher vor. „Zu viel“ ist subjektiv. Es kommt darauf an, wie viel Speicher Sie verwenden möchten, wie viele Elemente zwischengespeichert werden sollen, und wie oft diese Elemente abgerufen werden sollen. Wenn für das Zwischenspeichern im Arbeitsspeicher zu viele Daten vorliegen, sollten Sie auf jeden Fall das Zwischenspeichern von Daten in Text- oder XML-Dateien auf den Festplatten des Webservers in Erwägung ziehen. Sie können sich für eine Kombination des Zwischenspeicherns von Daten auf Festplatten und im Arbeitsspeicher entscheiden, um die optimale Zwischenspeicherungsstrategie für Ihre Site zu erhalten.

Beachten Sie, dass das Abrufen von Daten auf der Festplatte beim Ermitteln der Leistung einer einzelnen ASP-Seite nicht immer schneller als das Abrufen von Daten aus einer Datenbank ist. Durch Zwischenspeichern wird jedoch die Belastung der Datenbank und des Netzwerkes verringert. Bei einer hohen Belastung wird der Durchsatz hierdurch wesentlich verbessert. Das Zwischenspeichern kann beim Zwischenspeichern der Ergebnisse einer kostspieligen Abfrage, z. B. einer Mehrtabellenverknüpfung, einer komplexen gespeicherten Prozedur oder umfangreicher Resultsets, sehr effektiv sein. Testen Sie wie üblich die konkurrierenden Schemas.

ASP und COM stellen mehrere Tools zum Erstellen von festplattenbasierten Zwischenspeicherungsschemas bereit. Die ADO-Funktionen Save() und Open() des ADO-Recordsets speichern und laden Recordsets von der Festplatte. Mithilfe dieser Methoden könnten Sie den Beispielcode des Tipps zum Zwischenspeichern von Anwendungsdaten weiter oben neu schreiben, indem Sie den Code, der das Application-Objekt schreibt, durch eine Save()-Funktion zum Speichern in einer Datei ersetzen.

Es gibt einige weitere Komponenten, die mit Dateien eingesetzt werden können:

  1. Scripting.FileSystemObject ermöglicht das Erstellen, Lesen und Schreiben von Dateien. 
  2. MSXML, der zu Internet Explorer gehörende Microsoftä XML-Parser, unterstützt das Speichern und Laden von XML-Dokumenten. 
  3. Das LookupTable-Objekt (Beispiel, im MSN verwendet) eignet sich hervorragend zum Laden einfacher Listen von der Festplatte.

Zum Schluss sollten Sie das Zwischenspeichern der Datenpräsentation anstelle der Daten selbst auf der Festplatte in Erwägung ziehen. Vorgerenderter HTML-Inhalt kann als HTM- oder ASP-Datei auf der Festplatte gespeichert werden. Hyperlinks können direkt auf diese Dateien verweisen. Sie können das Generieren von HTML mit kommerziellen Tools automatisieren, wie z. B. Xbuilder oder den Funktionen zur Internetveröffentlichung von Microsoftä SQL Serverä. Stattdessen können Sie auch HTML-Ausschnitte in einer ASP-Datei aufnehmen. Sie können HTML-Dateien außerdem mithilfe von FileSystemObject von der Festplatte lesen oder XML für eine frühe Darstellung verwenden.

 

ASP Tipp 4: Vermeiden Sie das Zwischenspeichern von nicht beweglichen Komponenten in den Objekten „Application“ oder „Session“

Während sich das Zwischenspeichern von Daten im Application- oder Session-Objekt empfiehlt, kann das Zwischenspeichern von COM-Objekten große Nachteile haben. Es liegt oft nahe, häufig verwendete COM-Objekte in das Application- oder Session-Objekt abzulegen. Leider führen viele COM-Objekte, darunter alle in Visual Basic 6.0 oder früher verfassten, beim Speichern des Application- oder Session-Objekts zu schwerwiegenden Engpässen.

Insbesondere nicht bewegliche Komponenten führen beim Zwischenspeichern im Application- oder Session-Objekt zu Leistungsengpässen. Eine bewegliche Komponente ist eine mit ThreadingModel=Both markierte Komponente, die den FTM (Free-threaded Marshaler) aggregiert, oder eine mit ThreadingModel=Neutral markierte Komponente. (Das neutrale Modell wird erstmals in Windows 2000 und COM+ verwendet.) Folgende Komponenten sind nicht beweglich:

  1. Freethread-Komponenten (es sei denn, sie aggregieren den FTM)
  2. Apartmentthread-Komponenten
  3. Singlethread-Komponenten

Konfigurierte Komponenten (Microsoft Transaction Server (MTS)/COM+-Bibliothek und Serverpakete/-anwendungen) sind nicht beweglich, es sei denn, sie sind neutralthreaded. Apartmentthread-Komponenten und andere nicht bewegliche Komponenten funktionieren am besten im Gültigkeitsbereich der Seite (d. h. sie werden auf einer einzelnen ASP-Seite erstellt und gelöscht).

In IIS 4.0 wurde eine mit ThreadingModel=Both markierte Komponente als beweglich angesehen. In IIS 5.0 reicht das nicht länger aus. Die Komponente muss nicht nur mit Both markiert sein, sondern muss auch den FTM aggregieren. Der Artikel zur Beweglichkeit beschreibt, wie mit der Active Template Library geschriebene C++-Komponenten dazu veranlasst werden, den FTM zu aggregieren. Wenn Ihre Komponente Schnittstellenzeiger zwischenspeichert, müssen auch diese Zeiger selbst beweglich sein oder in der COM-GIT (Global Interface Table) gespeichert sein. Wenn sich eine Boththread-Komponente nicht zum Aggregieren des FTM neu kompilieren lässt, können Sie sie als ThreadingModel=Neutral markieren. Wenn IIS keine Beweglichkeitsprüfung durchführen soll (d. h. wenn nicht bewegliche Komponenten nicht im Gültigkeitsbereich des Application- oder Session-Objekts gespeichert werden sollen), können Sie AspTrackThreadingModel stattdessen in der Metabasis auf True festlegen. Es wird davon abgeraten, AspTrackThreadingModel zu ändern.

IIS 5.0 gibt einen Fehler aus, wenn Sie versuchen, eine nicht bewegliche, mit Server.CreateObject erstellte Komponente im Application-Objekt zu speichern. Sie können dies durch Verwenden von <object runat=server scope=application …> in der Datei Global.asa umgehen. Davon wird aber abgeraten, da dies wie unten erläutert zu Marshalling und Serialisierung führt.

Was läuft beim Zwischenspeichern nicht beweglicher Komponenten schief? Eine nicht bewegliche, im Session-Objekt zwischengespeicherte Komponente „bindet“ das Session-Objekt an einen ASP-Arbeitsthread. ASP verwaltet einen Pool von Arbeitsthreads, die von Diensten angefordert werden. Normalerweise wird eine neue Anforderung vom ersten verfügbaren Arbeitsthread verarbeitet. Wenn eine Sitzung an einen Thread gebunden ist, muss die Anforderung warten, bis der verknüpfte Thread verfügbar wird. Hierzu eine Analogie, die dies möglicherweise verständlicher macht: Sie gehen zum Supermarkt, kaufen Lebensmittel und bezahlen für diese an Kasse 3. Danach müssen Sie beim Einkaufen in diesem Supermarkt jedes Mal an Kasse 3 bezahlen, selbst wenn die Schlangen an anderen Kassen kürzer sind, oder es Kassen ohne Warteschlangen gibt.

Das Speichern nicht beweglicher Komponenten im Gültigkeitsbereich des Application-Objekts wirkt sich noch negativer auf die Leistung aus. ASP muss einen Spezialthread erstellen, um nicht bewegliche Komponenten im Gültigkeitsbereich des Application-Objekts auszuführen. Dies hat zwei Konsequenzen: Alle Aufrufe müssen zu diesem Thread gemarshallt und alle Aufrufe müssen serialisiert werden. Marshalling bedeutet, dass die Parameter in einem freigegebenen Bereich des Arbeitsspeichers gespeichert werden müssen. Am Spezialthread muss eine kostspielige Kontextänderung durchgeführt und die Methode der Komponente ausgeführt werden. Die Ergebnisse werden in einen freigegebenen Bereich gemarshallt, und eine weitere kostspielige Kontextänderung gibt die Kontrolle an den Originalthread zurück. Serialisierung bedeutet, dass alle Methoden nacheinander ausgeführt werden. Es ist nicht möglich, dass zwei unterschiedliche ASP-Arbeitsthreads gleichzeitig Methoden an einer freigegebenen Komponente ausführen. Dadurch wird Parallelität, insbesondere auf Mehrprozessorcomputern, verhindert. Am schlimmsten ist aber, dass allen nicht beweglichen Komponenten im Gültigkeitsbereich des Application-Objekts ein Thread (der „Host-STA“) gemeinsam ist. Dadurch werden die Auswirkungen der Serialisierung noch verstärkt.

Schwirrt Ihnen der Kopf? Dann dürften diese allgemeinen Regeln helfen. Wenn Sie Objekte in Visual Basic (6.0) oder früher schreiben, zwischenspeichern Sie sie nicht im Application- oder Session-Objekt. Wenn Ihnen das Threading-Modell eines Objekts nicht bekannt ist, sollten Sie es nicht zwischenspeichern. Anstatt nicht bewegliche Objekte zwischenzuspeichern, empfiehlt es sich, diese auf jeder Seite zu erstellen und freizugeben. Die Objekte werden direkt auf dem ASP-Arbeitsthread ausgeführt, so dass es nicht zu Marshalling oder Serialisierung kommt. Die Leistung ist angemessen, wenn die COM-Objekte im IIS-Feld ausgeführt werden, und wenn das Initialisieren und Löschen der COM-Objekte nicht besonders zeitaufwendig ist. Beachten Sie, dass Singlethread-Objekte nicht auf diese Weise verwendet werden sollten. Seien Sie vorsichtig: VB kann Singlethread-Objekte erstellen! Wenn Sie Singlethread-Objekte auf diese Weise (z. B. als Microsoft Excel-Tabelle) verwenden müssen, sollten Sie keinen hohen Durchsatz erwarten.

ADO-Recordsets können problemlos zwischengespeichert werden, wenn ADO als Freethread-Komponente markiert ist. Verwenden Sie die Datei Makfre15.bat, um ADO als Freethread-Komponente zu markieren. Diese befindet sich in der Regel im Verzeichnis \\Programme\Gemeinsame Dateien\System\ADO.

Warnung ADO sollte nicht als Freethread-Komponente markiert werden, wenn Microsoft Access als Datenbank verwendet wird. Das ADO-Recordset muss außerdem abgetrennt sein. Wenn Sie die ADO-Konfiguration auf Ihrer Site nicht steuern können (z. B. wenn Sie als unabhängiger Softwarehersteller eine Webanwendung an Kunden verkaufen, die ihre eigenen Konfigurationen verwalten), ist es im Allgemeinen wahrscheinlich besser, Recordsets nicht zwischenzuspeichern.

Wörterbuchkomponenten stellen ebenfalls bewegliche Objekte dar. Das LookupTable-Objekt lädt Daten aus einer Datendatei und ist sowohl für Kombinationsfelddaten als auch Konfigurationsinformationen geeignet. Das PageCache-Objekt von Duwamish Books stellt ebenso wie das Caprock-Lexikon Wörterbuchsemantiken bereit. Diese Objekte oder Ableitungen davon können die Grundlage einer effektiven Zwischenspeicherungsstrategie bilden. Beachten Sie, dass das Scripting.Dictionary-Objekt NICHT beweglich ist und nicht im Gültigkeitsbereich eines Application- oder Session-Objekts gespeichert werden sollte.

ASP Tipp 5: Zwischenspeichern Sie Datenbankverbindungen nicht in den Objekten „Application“ oder „Session“

Das Zwischenspeichern von ADO-Verbindungen ist normalerweise keine gute Strategie. Wenn ein Connection-Objekt im Application-Objekt gespeichert und auf allen Seiten verwendet wird, konkurrieren alle Seiten um diese Verbindung. Wenn das Connection-Objekt im Session-Objekt von ASP gespeichert wird, wird für jeden Benutzer eine Datenbankverbindung erstellt. Damit werden die Vorteile des Verbindungs-Pooling zunichte gemacht und der Webserver und die Datenbank unnötig belastet.

Anstatt Datenbankverbindungen zwischenzuspeichern, sollten Sie auf jeder Seite, die ADO verwendet, ADO-Objekte erstellen und löschen. Dies ist effizient, da das Verbindungs-Pooling in IIS integriert ist. Genauer gesagt, aktiviert IIS OLEDB- und ODBC-Verbindungs-Pooling automatisch. Dadurch wird auf jeder Seite ein effizientes Erstellen und Löschen von Verbindungen sichergestellt.

Da verbundene Recordsets eine Referenz auf eine Datenbankverbindung speichern, sollten diese nicht im Application- oder Session-Objekt zwischengespeichert werden. Sie können abgetrennte Recordsets, die keine Referenz auf ihre Datenverbindung enthalten, aber problemlos zwischenspeichern. Gehen Sie folgendermaßen vor, um ein Recordset abzutrennen:

Set rs = Server.CreateObject(„ADODB.RecordSet“)

rs.CursorLocation = adUseClient ‚ step 1

‚ Populate the recordset with data

rs.Open strQuery, strProv

‚ Now disconnect the recordset from the data provider and data source

rs.ActiveConnection = Nothing ‚ step 2

Weitere Informationen zum Verbindungs-Pooling finden Sie in den Verweisen auf ADO und SQL Server.

ASP Tipp 6: Verwenden Sie das „Session“-Objekt mit Umsicht

Nachdem Ihnen nun die Vorteile des Zwischenspeicherns im Application- und Session-Objekt bekannt sind, schlagen wir vor, das Session-Objekt zu meiden. Wie Sie im Folgenden sehen werden, haben Sitzungen, die auf viel verwendeten Sites verwendet werden, mehrere Nachteile. Bei viel verwendeten Sites handelt es sich um Sites mit Anforderungen von Hunderten von Seiten pro Sekunde oder Tausenden von gleichzeitigen Benutzern. Dieser Tipp ist noch wichtiger für Sites, die horizontal skalieren müssen, d. h. Sites, die mehrere Server zum Bewältigen der Belastung oder zum Implementieren von Fehlertoleranz verwenden. Bei kleineren Sites, wie z. B. Intranetsites, sind die praktischen Aspekte von Session-Objekten den Mehraufwand wert.

Zusammenfassend gilt, dass ASP für jeden Benutzer, der einen Webserver abfragt, ein Session-Objekt erstellt. Für jedes Session-Objekt ist (zusätzlich zu den in diesem gespeicherten Daten) ein Speicheraufwand von 10 KB erforderlich, und jedes Session-Objekt verlangsamt die Abfragen geringfügig. Das Session-Objekt bleibt aktiv, bis eine konfigurierbare Zeitüberschreitung (in der Regel 20 Minuten) erreicht wird.

Das größte Problem bei Session-Objekten ist nicht die Leistung, sondern die Skalierbarkeit. Session-Objekte sind nicht webserverübergreifend. Wenn ein Session-Objekt auf einem Server erstellt wurde, verbleiben seine Daten auf diesem. Wenn Sie Session-Objekte in einer Webservergruppe verwenden, müssen Sie also eine Strategie entwickeln, damit die Anfragen aller Benutzer an den Server geleitet werden, auf dem sich das Session-Objekt befindet. Dies wird als „feste Zuweisung“ eines Benutzers zu einem Webserver bezeichnet. Daraus wird der Begriff „fest zugewiesene Sitzungen“ abgeleitet. „Fest zugewiesene“ Benutzer verlieren Ihren Sitzungszustand, wenn der Webserver abstürzt, da die Session-Objekte nicht auf der Festplatte gespeichert sind.

Strategien zum Implementieren von fest zugewiesenen Sitzungen umfassen Hardware- und Softwarelösungen. Lösungen, wie z. B. das Programm für Netzwerklastenausgleich in Windows 2000 Advanced Server und Local Director von der Firma Cisco, können fest zugewiesene Sitzungen auf Kosten einer gewissen Skalierbarkeit implementieren. Diese Lösungen sind aber nicht perfekt. Das Einbringen eigener Softwarelösungen ist zurzeit auch nicht empfehlenswert (wir haben es mit ISAPI-Filtern und URL-Veränderungen u. ä. versucht)

Das Application-Objekt ist ebenfalls nicht serverübergreifend. Wenn Anwendungsdaten über die Webservergruppe freigegeben und aktualisiert werden müssen, müssen Sie eine Back-End-Datenbank verwenden. Schreibgeschätzte Anwendungsdaten sind jedoch in Webservergruppen weiterhin nützlich.  

Die meisten unternehmenskritischen Sites möchten mindesten zwei Webserver bereitstellen, selbst wenn der einzige Grund hierfür ein Erhöhen der Betriebszeit (der Umgang mit Ausfüllen und Serverwartung) ist. Aus diesem Grund müssen Sie beim Entwerfen einer unternehmenskritischen Anwendung entweder „fest zugewiesene Sitzungen“ implementieren oder Session-Objekte sowie sonstige Zustandsverwaltungsmethoden vermeiden, die den Benutzerzustand auf individuellen Webservern speichern.  

Wenn Sie keine Session-Objekte verwenden, denken Sie daran, sie zu deaktivieren. Sie können für Ihre Anwendung dazu den Internetdienste-Manager verwenden (siehe ISM-Dokumentation). Wenn Sie sich für die Verwendung von Session-Objekten entscheiden, können Sie ihre Auswirkungen auf die Leistung auf verschiedene Weise minimieren.

Sie können Inhalt, der keine Session-Objekte benötigt, (wie z. B. Hilfebildschirme, Besucherbereiche usw.) in eine separate ASP-Anwendung verschieben, für die Session-Objekte deaktiviert sind. Sie können ASP Seite für Seite darüber informieren, dass das Session-Objekt auf einer bestimmten Seite nicht benötigt wird. Positionieren Sie dazu folgende Anweisung am oberen Rand der ASP-Seite.

<% @EnableSessionState=False %>

Ein guter Grund für die Verwendung dieser Anweisung ist das interessante Problem, das bei Session-Objekten mit Framesets auftritt. ASP garantiert, dass zu einem bestimmten Zeitpunkt nur eine Anforderung von einem Session-Objekt ausgeführt wird. Wenn ein Browser für einen Benutzer mehrere Seiten anfordert, wird dadurch garantiert, dass zu einem bestimmten Zeitpunkt nur eine ASP-Anforderung beim Session-Objekt eingeht. Dadurch werden beim Zugreifen auf das Session-Objekt Multithread-Probleme vermieden. Dies führt jedoch auch dazu, dass alle Seiten in einem Frameset serialisiert, d. h. nacheinander statt simultan, gezeichnet werden. Der Benutzer muss daher u. U. lange warten, bis alle Frames angezeigt werden. Zusammenfasend gilt: Wenn bestimmte Frameset-Seiten nicht vom Session-Objekt abhängen, teilen Sie dies ASP mithilfe der Anweisung @EnableSessionState=False auf jeden Fall mit.  

Anstelle des Session-Objekts gibt es eine Reihe anderer Optionen zum Verwalten des Sitzungszustands. Für geringe Zustandsmengen (weniger als 4 KB) empfehlen sich Cookies, QueryString-Variablen und Variablen mit verborgenen Formularen. Für größere Datenmengen, wie z. B. Einkaufswagen, ist eine Back-End-Datenbank die beste Lösung. Es gibt viele Artikel über Zustandsverwaltungsmethoden in Webservergruppen. Weitere Einzelheiten finden Sie in den Referenzen zum Sitzungszustand.

 

ASP Tipp 7: Verkapseln Sie Code in COM-Objekten

Wenn Sie VBScript oder JScript vermehrt verwenden, können Sie in vielen Fällen die Leistung verbessern, indem Sie den Code in ein kompiliertes COM-Objekt verschieben. Kompilierter Code wird normalerweise schneller ausgeführt als interpretierter Code. Kompilierte COM-Objekte können über die „Auflösung zur Kompilierungszeit“, eine effizientere Methode zum Aufrufen von COM-Objektmethoden als die vom Skript verwendete „Auflösung zur Laufzeit“, auf andere COM-Objekte zugreifen.

Das Verkapseln von Code in COM-Objekten hat (abgesehen von der Leistung) einige Vorteile.

  1. COM-Objekt eignen sich gut zum Trennen der Präsentationslogik von der Geschäftslogik.
  2. COM-Objekte ermöglichen die Wiederverwendung von Code.
  3. Vielen Entwicklern füllt das Debuggen von Code, der in VB, C++ oder Visual J++ geschrieben wurde, leichter als das Debuggen von ASP.  

COM-Objekte haben Nachteile, darunter die anfängliche Entwicklungszeit und der Bedarf an unterschiedlichen Programmierungskenntnissen. Beachten Sie, dass das Verkapseln kleiner ASP-Beträge eher zu Leistungseinbußen als Leistungssteigerungen führt. Dies ist normalerweise der Fall, wenn ein geringer Umfang an ASP-Code in ein COM-Objekt eingefügt wird. Hier macht der Aufwand beim Erstellen und Aufrufen des COM-Objekts die Vorteile des kompilierten Codes zunichte. Sie werden die ideale Kombination aus ASP-Skript und COM-Objektcode zum Produzieren der optimalen Leistung nur durch Ausprobieren finden. Beachten Sie, dass Microsoft die Leistung von Skripts und ADO in Windows 2000/IIS 5.0 im Vergleich zu Windows NTä 4.0/IIS 4.0 enorm verbessert hat. Aus diesem Grund hat sich der Leistungsvorteil von kompiliertem Code im Vergleich zu ASP-Code seit der Einführung von IIS 5.0 verringert.

Ausführliche Diskussionen über die Vor- und Nachteile der Verwendung von COM-Objekten in ASP finden Sie in folgenden Dokumenten: „ASP Component Guidelines“ und „Programming Distributed Applications with COM and Microsoft Visual Basic 6.0“. Wenn Sie COM-Komponenten bereitstellen, müssen Sie diese unbedingt Belastungstests unterzogen werden. Im Prinzip sollten alle ASP-Anwendungen automatisch einem Belastungstest unterzogen werden.

 

Tipp 8: Rufen Sie Ressourcen spät ab, aber geben Sie sie früh frei

Hier ist ein kurzer Tipp für Sie. Im Allgemeinen sollten Ressourcen spät abgerufen und früh freigegeben werden. Dies gilt sowohl für COM-Objekte als auch für Dateihandles und andere Ressourcen.  

ADO-Verbindungen und -Recordsets sind die besten Kandidaten für diese Optimierung. Wenn Sie ein Recordset nicht mehr benötigen, z. B. nachdem Sie eine Tabelle anhand der enthaltenen Daten erstellt haben, geben Sie sie sofort frei, statt zu warten, bis das Seitenende erreicht wird. Legen Sie die VBScript-Variable gewohnheitsmäßig auf Nothing fest. Lassen Sie das Recordset nicht einfach aus dem Gültigkeitsbereich herausfallen. Geben Sie außerdem alle verwandten Command- oder Connection-Objekte frei (Vergessen Sie nicht die Funktion Close() für Recordsets oder Connection-Objekte aufzurufen, bevor Sie diese auf = Nothing festlegen.) Dadurch wird der Zeitraum verkürzt, in dem die Datenbank Ressourcen für Sie jonglieren muss, und die Datenbankverbindung wird sobald wie möglich an den Verbindungs-Pool freigegeben.

 

ASP Tipp 9: Eine prozessexterne Ausführung gibt der Leistung auf Kosten der Zuverlässigkeit den Vorzug

Sowohl ASP als auch MTS/COM+ enthalten Konfigurationsoptionen, mit denen Sie einen Kompromiss zwischen Zuverlässigkeit und Leistung erzielen. Sie müssen sich beim Erstellen und Bereitstellen Ihrer Anwendung über diese Kompromisse im Klaren sein.  

ASP-Optionen

Sie können ASP-Anwendungen so konfigurieren, dass sie auf eine von drei Arten ausgeführt werden. In IIS 5.0 wurde der Begriff „Isolationsstufe“ zum Beschreiben dieser Optionen eingeführt. Es gibt drei Werte für die Isolationsstufe: Niedrig, Mittel und Hoch:

  1. Niedrige Isolation. Diese Option ist die schnellste und wird in allen Versionen von IIS unterstützt. Sie führt ASP in Inetinfo.exe, dem primären IIS-Prozess, aus. Wenn die ASP-Anwendung abstürzt, stürzt auch IIS ab. (Um IIS unter IIS 4.0 neu zu starten, überwachen Webmaster die Site mit Tools, wie z. B. InetMon, und lösen Stapeldateien aus, um einen ausgefallenen Server neu zu starten. In IIS 5.0 wird ein zuverlässiger Neustart eingeführt, der einen ausgefallenen Server automatisch neu startet.) 
  2. Mittlere Isolation. Diese neue Stufe wird in IIS 5.0 eingeführt. Sie wird auch als prozessexterne Stufe bezeichnet, da ASP außerhalb des IIS-Prozess ausgeführt wird. Bei der mittleren Isolation ist allen ASP-Anwendungen, die laut Konfiguration mit einer mittleren Isolationsstufe ausgeführt werden, der gleiche Prozessbereich gemeinsam. Dadurch werden zum Ausführen von mehreren prozessexternen ASP-Anwendungen in einem Feld weniger Prozesse benötigt. Mittel ist die Standardisolationsstufe in IIS 5.0.
  3. Hohe Isolation. Die in IIS 4.0 und IIS 5.0 unterstützte hohe Isolation ist ebenfalls prozessextern. Sollte ASP abstürzen, stürzt der Webserver nicht gleichzeitig ab. Die ASP-Anwendung wird bei der nächsten ASP-Anfrage automatisch neu gestartet. Bei der hohen Isolation wird jede ASP-Anwendung, die laut Konfiguration mit einer hohen Isolationsstufe ausgeführt wird, in ihrem eigenen Prozessbereich ausgeführt. Dadurch werden ASP-Anwendungen voneinander geschätzt. Der Nachteil ist, dass für jede ASP-Anwendung ein separater Prozess nötig ist. Wenn Dutzende von Anwendungen das gleiche Feld als Host verwenden, kann sich der Aufwand wesentlich erhöhen.  

Welche Option ist die Beste? In IIS 4.0 hatten prozessexterne Ausführungen starke Leistungseinbußen zur Folge. In IIS 5.0 haben wir uns bemüht, die Kosten einer prozessexternen Ausführung von ASP-Anwendungen zu minimieren. In den meisten Tests liefen prozessexterne ASP-Anwendungen in IIS 5.0 schneller als prozessinterne Anwendungen in IIS 4.0. Unabhängig davon bietet eine prozessinterne Ausführung (niedrige Isolationsstufe) auf beiden Plattformen auch weiterhin die beste Leistung. Eine niedrige Isolationsstufe bringt aber nicht besonders viele Vorteile, wenn die Trefferrate oder der maximale Durchsatz relativ niedrig sind. Aus diesem Grund sollten Sie die niedrige Isolationsstufe erst benötigen, wenn pro Webserver mehrere Tausend Seiten pro Sekunden benötigt werden. Testen Sie die verschiedenen Optionen für mehrere Konfigurationen, um herauszufinden, welche Kompromisse Sie einzugehen bereit sind.  

Anmerkung Wenn Sie ASP-Anwendungen prozessextern (mit mittlerer oder hoher Isolation) ausführen, werden Sie in MTS auf NT4 und COM+ auf Windows 2000 ausgeführt, d. h. auf NT4 werden sie in Mtx.exe und auf Windows 2000 in DllHost.exe ausgeführt. Die Ausführung dieser Prozesse ist im Task-Manager zu sehen. Sie können auch sehen, wie IIS MTS-Pakete oder COM+-Anwendungen für prozessexterne ASP-Anwendungen konfiguriert.  

COM-Optionen

Für COM-Komponenten gibt es ebenfalls drei Konfigurationsoptionen, die den ASP-Optionen jedoch nicht genau entsprechen. Für COM-Komponenten gibt es folgende Optionen: unkonfiguriert, als Bibliotheksanwendungen konfiguriert oder als Serveranwendungen konfiguriert. Unkonfiguriert bedeutet, dass die Komponente nicht in COM+ registriert ist. Diese Komponente wird im Prozessbereich des Aufrufers ausgeführt, d. h. sie ist „prozessintern“. Bibliotheksanwendungen sind ebenfalls prozessintern, profitieren aber von den COM+-Diensten, darunter Sicherheit, Transaktionen und Kontextunterstützung. Serveranwendungen sind so konfiguriert, dass sie in ihrem eigenen Prozessbereich ausgeführt werden. 

Unkonfigurierte Komponenten haben möglicherweise einen geringen Vorteil gegenüber Bibliotheksanwendungen. Der Leistungsvorteil von Bibliotheksanwendungen im Vergleich zu Serveranwendungen ist jedoch wesentlich deutlicher. Grund hierfür ist, dass Bibliotheksanwendungen im gleichen Prozess wie ASP, Serveranwendungen dagegen aber in ihrem eigenen Prozess ausgeführt werden. Prozessübergreifende Aufrufe sind kostspieliger als prozessinterne Aufrufe. Beim Weiterleiten von Daten wie z. B. Recordsets zwischen Prozessen müssen alle Daten zwischen beiden Prozessen kopiert werden.  

Großer Nachteil! Wenn Sie beim Verwenden von COM-Serveranwendungen Objekte zwischen ASP und COM weiterleiten, stellen Sie sicher, dass „Marshalling nach Wert“ (marshal-by-value, MBV) implementiert ist. Objekte, die MBV implementieren, kopieren sich selbst von einem Prozess zu einem anderen. Dies ist besser als die Alternative, bei der das Objekt im Erstellerprozess verbleibt und der andere Prozess wiederholt in den Erstellungsprozess eingreift, um das Objekt zu verwenden. Abgetrennte ADO-Recordsets marshallen nach Wert, verbundene Recordsets nicht. Das Scripting.Dictionary-Objekt implementiert MBV nicht und sollte nicht zwischen Prozessen weitergegeben werden. Zum Schluss noch ein Rat für alle VB-Programmierer: MBV wird NICHT durch Weitergabe eines ByVal-Parameters erzielt, sondern vom ursprünglichen Komponentenverfasser implementiert.  

Vorgehensweise

Wenn wir Konfigurationen mit akzeptablen Kompromissen zwischen Leistung und Zuverlässigkeit empfehlen sollten, würden diese wie folgt lauten:

  1. Verwenden Sie in IIS 4.0 die niedrige Isolationsstufe sowie MTS-Serverpakete. 
  2. Verwenden Sie in IIS 5.0 die mittlere Isolationsstufe sowie COM+-Bibliotheksanwendungen.  

Hierbei handelt es sich um sehr allgemeine Richtlinien. Hostunternehmen führen ASP in der Regel mit einer mittleren oder hohen Isolationsstufe aus, wohingegen Webserver mit nur einem Zweck mit einer niedrigen Isolation ausgeführt werden können. Ermitteln Sie die Kompromisse, und entscheiden Sie dann, welche Konfiguration Ihren Bedürfnissen entspricht.

 

ASP Tipp 10: Verwenden Sie „Option Explicit“

Verwenden Sie Option Explicit in Ihren ASP-Dateien Wenn diese Anweisung am oberen Rand von ASP-Dateien positioniert wurde, muss der Entwickler alle zu verwendenden Variablen deklarieren. Viele Programmierer finden dies beim Debuggen von Anwendungen hilfreich, denn dadurch ist die Gefahr von Tippfehlern und das daraus resultierende versehentliche Erstellen neuer Variablen wesentlich geringer (z. B. MyXLMString=… anstatt MyXMLString=).  

Es ist aber vielleicht von noch größerer Wichtigkeit, dass deklarierte Variablen schneller sind als undeklarierte. Die Skriptlaufzeit verweist nämlich hinter den Kulissen auf undeklarierte Variablen anhand des Namens, jedes Mal, wenn sie verwendet werden. Deklarierten Variablen wird dagegen entweder zur Kompilierzeit oder zur Laufzeit eine Ordinalzahl zugewiesen. Im Folgenden wird auf deklarierte Variablen anhand dieser Ordinalzahl verwiesen. Da Option Explicit die Deklaration von Variablen erzwingt, stellt sie sicher, dass alle Variablen deklariert werden und somit schnell auf sie zugegriffen werden kann.