4 Möglichkeiten zur Verbesserung der ASP.NET-Leistung bei Spitzenlasten

 

Einleitung

ASP.NET erfreut sich bei der Entwicklung von Webanwendungen immer größerer Beliebtheit. Viele dieser Anwendungen weisen einen hohen Datenverkehr auf und bedienen Millionen von Benutzern. Daher haben diese Anwendungen einen großen Einfluss auf das Geschäft und sind daher sehr wichtig.

Interessanterweise ist die ASP.NET-Anwendungsarchitektur auf der Anwendungsebene sehr skalierbar. Und auch das HTTP-Protokoll ist zustandslos. Beides bedeutet, dass Sie Ihre ASP.NET-Anwendung in einer Webfarm mit Lastenausgleich ausführen können, in der jede HTTP-Anfrage an den am besten geeigneten Webserver weitergeleitet wird. Dadurch können Sie ganz einfach weitere Webserver zu Ihrer Webfarm hinzufügen, wenn Ihr Benutzerverkehr zunimmt. Und dadurch ist Ihre ASP.NET-Anwendungsebene sehr skalierbar. Aber was meine ich hier mit Skalierbarkeit?

Unter Skalierbarkeit versteht man im Wesentlichen die Fähigkeit, auch bei Spitzenlasten eine hohe Leistung zu liefern. Wenn also die Reaktionszeit Ihrer ASP.NET-Anwendungsseite bei 10 Benutzern sehr schnell ist und bei 100,000 Benutzern genauso schnell bleibt, dann ist Ihre ASP.NET-Anwendung skalierbar. Wenn sich Ihre ASP.NET-Antwortzeit jedoch verlangsamt, wenn die Anzahl der Benutzer steigt, ist Ihre Anwendung nicht skalierbar.

 

Das Problem: Skalierbarkeitsengpässe

Trotz einer sehr skalierbaren Architektur auf der Anwendungsebene sind ASP.NET-Anwendungen heute mit großen Skalierbarkeitsengpässen konfrontiert. Diese Engpässe treten in vier verschiedenen Bereichen auf:

  1. Anwendungsdatenbank
  2. ASP.NET-Sitzungszustandsspeicherung
  3. ASP.NET View State
  4. ASP.NET-Seitenausführung für statische Ausgabe

Lassen Sie mich die einzelnen Punkte im Folgenden näher erläutern.

 

Anwendungsdatenbank

Anwendungsdatenbanken wie SQL Server oder Oracle werden schnell zu einem Skalierbarkeitsengpass, wenn Sie die Transaktionslast erhöhen. Dies liegt daran, dass Sie die Datenbankebene zwar durch den Kauf eines leistungsstärkeren Datenbankservers vergrößern können, eine Skalierung durch das Hinzufügen weiterer Server zur Datenbankebene jedoch nicht möglich ist. Es kommt beispielsweise sehr häufig vor, dass auf der Anwendungsebene 10 bis 20 Server vorhanden sind, auf der Datenbankebene ist dies jedoch nicht möglich.

 

ASP.NET-Sitzungszustandsspeicherung

Darüber hinaus muss der ASP.NET-Sitzungsstatus irgendwo gespeichert werden. Und die von Microsoft bereitgestellten Standardoptionen sind InProc, StateServer und SqlServer. Leider weisen alle drei Optionen erhebliche Leistungs- und Skalierbarkeitsprobleme auf. InProc und StateServer zwingen Sie dazu, Sticky-Sitzungen zu verwenden und alle HTTP-Anfragen auf demselben Server zu senden, auf dem die Sitzung erstellt wurde. Wenn Sie StateServer als eigenständigen Server konfigurieren, um Sticky Sessions zu vermeiden, wird StateServer zu einem Single Point of Failure und seine Leistung wird ebenfalls zu einem großen Problem. Und SqlServer speichert ASP.NET-Sitzungen in der SQL Server-Datenbank als BLOBs. Außerdem gibt es bei diesem Ansatz ernsthafte Leistungs- und Skalierbarkeitsprobleme.

 

ASP.NET View State

ASP.NET View State ist eine codierte, versteckte Zeichenfolge (oft Hunderte von KB groß), die als Teil der HTTP-Antwort an den Browser des Benutzers gesendet wird. Der Browser macht damit nichts und sendet es im Falle eines HTTP-Post-Backs an den Webserver zurück. Dies verlangsamt die Reaktion der ASP.NET-Seite, belastet die Netzwerkkarten des Webservers stärker und verbraucht außerdem viel zusätzliche Bandbreite. Und wie Sie wissen, ist Bandbreite nicht billig.

 

ASP.NET-Seitenausführung für statische Ausgabe

Schließlich ASP.NET framework Führt eine ASP.NET-Seite anhand einer Benutzeranforderung aus, auch wenn sich die Seitenausgabe gegenüber der vorherigen Anforderung nicht ändert. Dies kann in Umgebungen mit wenigen Transaktionen in Ordnung sein. Aber in einer Umgebung mit hohem Transaktionsaufkommen, in der alle Ressourcen bereits an ihre Grenzen stoßen, kann diese zusätzliche Ausführung recht kostspielig werden und einen Engpass bei der Skalierbarkeit darstellen.

Wie das Sprichwort sagt: „Die Stärke jeder Kette ist nur so stark wie ihr schwächstes Glied.“ Solange es also irgendwo in der ASP.NET-Anwendungsumgebung Skalierbarkeitsengpässe gibt, wird die gesamte Anwendung langsamer und kommt sogar zum Stillstand.

Und ironischerweise geschieht dies unter Spitzenlast, wenn Sie ein Höchstmaß an Geschäftsaktivität ausüben. Daher sind die Auswirkungen einer Verlangsamung oder Ausfallzeit für Ihr Unternehmen viel kostspieliger.

ASP.NET steht vor Skalierbarkeitsengpässen
Abbildung 1: ASP.NET steht vor Skalierbarkeitsengpässen
 

NoSQL Database Nicht die Antwort

NoSQL database Die Bewegung begann als Folge der Skalierbarkeitsprobleme in relationalen Datenbanken. NoSQL database Partitioniert die Daten auf mehrere Server und ermöglicht eine horizontale Skalierung wie bei der Anwendungsschicht.

Aber NoSQL database erfordert, dass Sie Ihre relationale Datenbank aufgeben und Ihre Daten in eine NoSQL database. Und das ist aus einer Vielzahl von Gründen leichter gesagt als getan und in vielen Fällen tatsächlich nicht möglich.

NoSQL databases verfügen nicht über die gleichen Datenverwaltungs- und Suchfunktionen wie relationale Datenbanken und möchten, dass Sie Daten auf eine völlig andere Art und Weise als in relationalen Datenbanken speichern. Darüber hinaus ist das Ökosystem rund um relationale Datenbanken für die meisten Unternehmen zu stark, um es aufzugeben.

Dadurch NoSQL databases sind nur dann nützlich, wenn Sie mit unstrukturierten Daten arbeiten. Und die meisten ASP.NET-Anwendungen befassen sich mit Geschäftsdaten, die überwiegend strukturiert und für relationale Datenbanken geeignet sind. Daher können diese Daten nicht in eine verschoben werden NoSQL database einfach.

Und selbst diejenigen, die am Ende ein verwenden NoSQL database Tun Sie dies für eine kleine Teilmenge ihrer Gesamtdaten, die als unstrukturiert betrachtet werden können. Und sie nutzen NoSQL database zusammen mit ihrer vorhandenen relationalen Datenbank.

Daher müssen Sie in den meisten Fällen mit Ihrer relationalen Datenbank leben und eine andere Lösung für Ihre Skalierbarkeitsprobleme finden. Glücklicherweise gibt es eine sehr praktikable Lösung, auf die ich weiter unten eingehen werde.

 

Die Lösung: Verteilter In-Memory-Cache

Die Lösung für alle oben genannten Probleme besteht darin, In-Memory Distributed Cache in Ihrer Anwendungsbereitstellung zu verwenden NCache. NCache ist ein Verteilter Open-Source-Cache für .NET, das extrem schnell und linear skalierbar ist. Stellen Sie sich das als einen In-Memory-Objektspeicher vor, der ebenfalls verteilt ist. Durch die In-Memory-Speicherung ist es extrem schnell und durch die Verteilung linear skalierbar.

Das Schöne an einem In-Memory Distributed Cache wie NCache besteht darin, dass Sie nicht aufgefordert werden, die Nutzung Ihrer vorhandenen relationalen Datenbank einzustellen. Sie können den Cache zusätzlich zu Ihrer relationalen Datenbank verwenden, da der Cache alle Engpässe bei der Skalierbarkeit relationaler Datenbanken beseitigt.

NCache Bietet lineare Skalierbarkeit
Abbildung 2: NCache Bietet lineare Skalierbarkeit

Wie sieht also ein verteilter In-Memory-Cache aus? NCache skalierbarer als eine relationale Datenbank? Also, NCache bildet einen Cluster von Cache-Servern und bündelt die CPU, den Speicher und andere Ressourcen aller dieser Server.

Und, NCache ermöglicht das Hinzufügen von Cache-Servern zur Laufzeit, ohne den Cache oder die Anwendung anzuhalten. Dadurch können Sie Ihre Anwendung linear skalieren und extreme Transaktionslasten bewältigen. Dies ist etwas, was Sie mit Ihrer relationalen Datenbank nicht tun können.

In-Memory Distributed Cache wie NCache skaliert linear, indem Sie zur Laufzeit Cache-Server zum Cache-Cluster (der Caching-Ebene) hinzufügen können. Aber welche Leistungszahlen sollten Sie von einer Lösung wie dieser erwarten? NCache.

Hier sind NCache Leistungszahlen. Sie können voll sehen NCache Leistungsbenchmark .

Leistungszahlen für NCache
Abbildung 3: Leistungszahlen für NCache

Wie Sie sehen, ähnelt ein In-Memory Distributed Cache NCache Bietet eine Leistung von weniger als einer Millisekunde für Lese- und Schreibvorgänge und ermöglicht Ihnen die lineare Skalierung Ihrer Transaktionskapazität durch einfaches Hinzufügen weiterer Cache-Server.

Sehen wir uns nun an, wie ein In-Memory Distributed Cache aussieht NCache Behebt verschiedene oben erwähnte Skalierbarkeitsengpässe.

 

Zwischenspeichern von Anwendungsdaten

Mit Application Data Caching können Sie Ihre Datenbankengpässe beseitigen. In-Memory Distributed Cache wie NCache ermöglicht es Ihnen, Anwendungsdaten zwischenzuspeichern und teure Datenbankfahrten zu reduzieren. Sie können davon ausgehen, dass 70–90 % des Datenbankdatenverkehrs zum verteilten In-Memory-Cache umgeleitet werden. Dies verringert den Druck auf Ihre Datenbank und ermöglicht eine schnellere Leistung sowie die Bewältigung größerer Transaktionslasten ohne Verlangsamung.

Customer Load(string customerId)
{
 // Key format: Customer:PK:1000
 string key = "Customers:CustomerID:" + customerId;
 Customer cust = (Customer) _cache[key];
 if (cust == null)
 { // Item not in cache so load from db
LoadCustomerFromDb(cust);
// Add item to cache for future reference
_cache.Insert(key, cust);
 }
 return cust;
}

Abbildung 4: Verwendung des verteilten In-Memory-Cache für das App-Daten-Caching

Anwendungsdaten-Caching bedeutet, dass Sie alle Anwendungsdaten zwischenspeichern, die Sie aus Ihrer relationalen Datenbank erhalten. Dies geschieht normalerweise in Form von Domänenobjekten (auch Entitäten genannt). Hier ist ein Beispiel für die Verwendung eines verteilten Caches NCache für das Zwischenspeichern von Anwendungsdaten.

 

Zwischenspeichern des ASP.NET-Sitzungsstatus

In-Memory Distributed Cache wie NCache ist auch ein großartiger Ort zum Speichern Ihres ASP.NET-Sitzungsstatus. Es ist viel schneller und skalierbarer als alle drei oben genannten Optionen (InProc, StateServer und SqlServer). NCache ist schneller, da es sich im Arbeitsspeicher befindet und eine Schlüsselwertschnittstelle bereitstellt, wobei der Wert ein „Objekt“ ist, das ein ASP.NET-Sitzungsstatus ist. Und es ist skalierbar, da es sich um einen verteilten Cache handelt.

Und, NCache Darüber hinaus repliziert es Sitzungen intelligent über seine umfangreichen Caching-Topologien, sodass selbst bei einem Ausfall eines Cache-Servers keine Sitzungsdaten verloren gehen. Diese Replikation ist erforderlich, weil NCache Stellt einen In-Memory-Speicher bereit und der Speicher verletzt den Speicher.

NCache Beschleunigt außerdem die Serialisierung des ASP.NET-Sitzungsstatusobjekts, die erforderlich ist, bevor es außerhalb des Prozesses gespeichert werden kann. NCache Dies geschieht mithilfe der Funktion „Dynamic Compact Serialization“, die zehnmal schneller ist als die reguläre .NET-Serialisierung. Sie können diese Funktion verwenden, ohne Codeänderungen vorzunehmen.

Sie können einstecken NCache Sitzungsstatusanbieter (SSP)-Modul zu Ihrer ASP.NET-Anwendung hinzufügen, indem Sie einige Änderungen in Ihrer web.config-Datei vornehmen, wie unten gezeigt.

<system.web>
 ...
 <assemblies>
<add assembly="Alachisoft.NCache.SessionStoreProvider, Version=4.3.0.0,
 Culture=neutral, PublicKeyToken=CFF5926ED6A53769" />
 </assemblies>
 <sessionState cookieless="false" regenerateExpiredSessionId="true"
 mode="Custom" customProvider="NCacheSessionProvider"
timeout="20">
<providers>
 <add name="NCacheSessionProvider"
 type="Alachisoft.NCache.Web.SessionState.NSessionStoreProvider"
 useInProc="false" cacheName="myDistributedCache"
 enableLogs="false“ writeExceptionsToEventLog="false” />
</providers>
 </sessionState>
 ...
</system.web>

Abbildung 5: Plug-in NCache als ASP.NET Session State Provider (SSP) in Web.Config

 

ASP.NET View State Caching

Wie das geht, habe ich bereits beschrieben ASP.NET View State ist eine verschlüsselte Zeichenfolge, die vom Webserver an den Browser des Benutzers gesendet wird, der sie dann im Falle eines HTTP-Postbacks an den Webserver zurücksendet. Aber mit Hilfe eines InMemory Distributed Cache wie NCache, können Sie dies zwischenspeichern ASP.NET View State auf dem Server und sendet stattdessen nur eine kleine eindeutige ID.

NCache hat eine implementiert ASP.NET View State Caching-Modul über einen benutzerdefinierten ASP.NET-Seitenadapter und ASP.NET PageStatePersister. Hier entlang, NCache fängt sowohl HTTP-Anfragen als auch -Antworten ab. Zum Reaktionszeitpunkt NCache Entfernt den „Wert“-Teil der codierten Zeichenfolge, speichert ihn zwischen und fügt stattdessen eine eindeutige Kennung (einen Cache-Schlüssel) in diesen „Wert“ ein.

Wenn dann die nächste HTTP-Anfrage eintrifft, fängt es diese erneut ab und ersetzt die eindeutige Kennung durch die tatsächliche codierte Zeichenfolge, die es zuvor im Cache abgelegt hat. Auf diese Weise bemerkt die ASP.NET-Seite keinen Unterschied und verwendet die codierte Zeichenfolge, die den Ansichtsstatus enthält, wie zuvor.

Das folgende Beispiel zeigt eine ASP.NET View State codierte Zeichenfolge ohne Caching und auch, was passiert, wenn Caching integriert ist.

//ASP.NET View State without Caching
<input id="__VIEWSTATE"
 	type="hidden"
 	name="__VIEWSTATE"
 	value="/wEPDwUJNzg0MDMxMDA1D2QWAmYPZBYCZg9kFgQCAQ9kFgICBQ9kFgJmD2QWAgIBD
		xYCHhNQcm2aW91c0NvbnRyb2xNb2RlCymIAU1pY3Jvc29mdC5TaGFyZVBvaW50Lld
		lYkNvbnRyb2xzLlNQQ29udHJbE1vZDA1XzRlMjJfODM3Y19kOWQ1ZTc2YmY1M2IPD
		xYCHhNQcm2aW91c0NvbnRyb2xNb2RlCymIAU1pY3Jvc29mdC5TaGFyZVBvaW50Lld
		lYkNvbnRyb2xzLlNQQ29udHJbE1vZDA1XzRlMjJfODM3Y19kOWQ1ZTc2YmY1M2IPD
		... ==" />
			
//ASP.NET View State with Caching
<input id="__VIEWSTATE"
	type="hidden"
	name="__VIEWSTATE"
	value="vs:cf8c8d3927ad4c1a84da7f891bb89185" />

Abbildung 6: ASP.NET View State Codierter String mit oder ohne Caching

 

ASP.NET-Ausgabecache für statische Seitenausgabe

ASP.NET bietet ein ASP.NET-Ausgabecache-Framework, um das Problem übermäßiger Seitenausführung zu beheben, selbst wenn sich die Seitenausgabe nicht ändert. Mit diesem Framework können Sie die Ausgabe entweder der gesamten Seite oder einiger Teile der Seite zwischenspeichern, sodass diese Seite beim nächsten Aufruf nicht ausgeführt wird und stattdessen die zwischengespeicherte Ausgabe angezeigt wird. Das Anzeigen einer bereits zwischengespeicherten Ausgabe ist viel schneller als das erneute Ausführen der gesamten Seite.

<caching>
   <outputCache defaultProvider ="NOutputCacheProvider">
     <providers>
       <add name="NOutputCacheProvider"
         type="Alachisoft.NCache.OutputCacheProvider.NOutputCacheProvider,
               Alachisoft.NCache.OutputCacheProvider, Version=x.x.x.x,
               Culture=neutral, PublicKeyToken=1448e8d1123e9096"
				  
               cacheName="myDistributedCache" exceptionsEnabled="false"
               writeExceptionsToEventLog="false" enableLogs="true” />"
     </providers>
   </outputCache>
</caching>

Abbildung 7: Einrichten des ASP.NET-Ausgabecache-Anbieters für NCache in Web.Config

NCache hat einen ASP.NET Output Cache Provider für .NET 4.0 oder spätere Versionen implementiert. Dies ermöglicht Ihnen das Einstecken NCache nahtlos und ohne Programmieraufwand. Im Falle von NCacheDieser Anbieter ist für einen verteilten In-Memory-Cache gedacht, der sich über mehrere Server erstreckt. Wenn Ihre ASP.NET-Anwendung also in einer Webfarm mit Lastenausgleich ausgeführt wird, ist die von Server 1 zwischengespeicherte Seitenausgabe sofort für alle anderen Server in der Webfarm verfügbar. Unten erfahren Sie, wie Sie es anschließen können NCache als ASP.NET-Ausgabecache-Anbieter.

 

Verteilte Cache-Architektur

ASP.NET-Anwendungen mit hohem Datenverkehr können es sich nicht leisten, auszufallen, insbesondere während der Spitzenzeiten. Für diese Art von Anwendungen gibt es drei wichtige Architekturziele, die einem guten In-Memory Distributed Cache entsprechen NCache bietet. Sie sind:

  1. Hohe Verfügbarkeit
  2. Lineare Skalierbarkeit
  3. Datenreplikation und Zuverlässigkeit

Lassen Sie mich die einzelnen Bereiche im Folgenden erläutern.

 

Hochverfügbarkeit

Eines der wichtigsten architektonischen Ziele von NCache besteht darin, eine hohe Verfügbarkeit und Cache-Elastizität zu erreichen. Und das geschieht durch die folgenden architektonischen Fähigkeiten:

  1. Selbstheilender Peer-to-Peer-Cache-Cluster: NCache baut einen Cluster von Cache-Servern über TCP/IP auf. Dieser Cluster hat eine Peer-to-Peer Architektur, was bedeutet, dass es keine Master/Slave-Knoten und kein Clustering nach Mehrheitsregeln gibt. Stattdessen ist jeder Knoten ein gleichberechtigter Peer. Das ermöglicht NCache um Situationen zu bewältigen, in denen ein Knoten ausfallen könnte und der Cluster sich automatisch anpasst und weiterläuft, ohne dass Ihre Anwendung unterbrochen wird.
  2. Dynamische Konfiguration: Das bedeutet, dass Sie keine Dinge in Konfigurationsdateien fest codieren müssen. Das ist weil NCache gibt zur Laufzeit viele Konfigurationsinformationen an Cache-Clients (d. h. Ihre Anwendungen) weiter. Wenn Sie also zur Laufzeit einen Cache-Server hinzufügen, wird die Cluster-Mitgliedschaft automatisch aktualisiert und der Cluster informiert alle Cache-Clients über diese Änderung. Es gibt eine Vielzahl anderer Konfigurationsänderungen, die auf die gleiche Weise gehandhabt werden.
  3. Unterstützung für Verbindungs-Failover: Hierbei handelt es sich um eine Funktion, die es dem Cache-Cluster und den Cache-Clients ermöglicht, ohne Unterbrechung weiterzuarbeiten, wenn ein Cache-Server ausfällt. Im Falle des Cache-Clusters habe ich bereits seine Selbstheilungseigenschaften besprochen, die diese Situation beheben. Im Falle von Cache-Clients bedeutet dies, dass der Cache-Client weiterhin arbeitet, indem er mit anderen Cache-Servern im Cluster interagiert.
 

Datenreplikation mit linearer Skalierbarkeit

Da In-Memory Distributed Cache gefällt NCache Da es Speicher als Speicher verwendet, muss es eine Datenreplikation ermöglichen, um die Zuverlässigkeit sicherzustellen. Gleichzeitig darf die lineare Skalierbarkeit jedoch nicht beeinträchtigt werden, da dies der wichtigste Grund für die Verwendung eines verteilten Caches ist NCache.

Hier sind einige NCache Caching-Topologien die dazu beitragen, diese beiden Ziele zu erreichen.

  1. Partitionierter Cache: NCache Partitioniert den Cache basierend auf der Anzahl der Cache-Server und weist jedem Cache-Server eine Partition zu. Außerdem wird die Anzahl der Partitionen angepasst, wenn Sie zur Laufzeit Cache-Server hinzufügen oder entfernen. Die Partitionierung ist die wichtigste Möglichkeit, lineare Skalierbarkeit sicherzustellen, denn wenn Sie weitere Server hinzufügen, erhöht diese Caching-Topologie die Gesamtspeichergröße und auch die CPU-Verarbeitungsleistung.
  2. Partitionierter Replikat-Cache: Zusätzlich zur Partitionierung NCache stellt außerdem Replikate für jede Partition bereit. Diese Replikate befinden sich auf anderen Cache-Servern als die Partition selbst, um sicherzustellen, dass die Replik sofort verfügbar ist, wenn ein Cache-Server zusammen mit seiner Partition ausfällt. Auf diese Weise wird Datenzuverlässigkeit gewährleistet. Indem jede Partition nur einmal auf einem anderen Cache-Server repliziert wird, NCache erreicht Datenzuverlässigkeit, ohne die lineare Skalierbarkeit zu beeinträchtigen.
  3. Client-Cache (nahe dem Cache): Eine weitere sehr wichtige Fähigkeit von NCache ist Client-Cache. Dabei handelt es sich um einen lokalen Cache, der sich auf dem Cache-Client-Rechner (nämlich Ihrem Web- oder App-Server) befindet und sogar InProc sein kann (d. h. er befindet sich in Ihrem Anwendungsprozess). Dies ist im Wesentlichen ein Cache über einem Cache und bietet extreme Leistungssteigerungen bei gleichzeitig zunehmender Skalierbarkeit NCache selbst, weil der Datenverkehr sogar zur Caching-Ebene abnimmt.
Partition-Replica-Caching-Topologie von NCache
Abbildung 8: Partition-Replica-Caching-Topologie von NCache

Wie Sie sehen, legt Partitioned-Replica Cache eine Partition und ein Replikat auf jedem Cache-Server ab. Außerdem wird sichergestellt, dass sich das Replikat aus Gründen der Zuverlässigkeit immer auf einem anderen Cache-Server befindet.

 

Zusammenfassung

Ich habe versucht, die häufigsten Leistungs- und Skalierbarkeitsengpässe hervorzuheben, mit denen ASP.NET-Anwendungen heute konfrontiert sind, und Ihnen zu zeigen, wie Sie diese mithilfe eines verteilten In-Memory-Cache überwinden können NCache. NCache ist ein verteilter Open-Source-Cache für .NET- und Java-Anwendungen. Sie können es also ohne Einschränkungen nutzen. Erfahren Sie mehr über NCache unter folgendem Link

Was macht man als nächstes?

© Copyright Alachisoft 2002 - Alle Rechte vorbehalten NCache ist eine eingetragene Marke der Diyatech Corp.