.NET Core und ASP.NET Core erfreuen sich aufgrund ihres einfachen Designs, ihrer geringen Größe, ihrer Open-Source-Natur und ihrer Kompatibilität mit Windows und Linux zunehmender Beliebtheit. Daher migrieren viele bestehende Anwendungen vom .NET Framework zu .NET Core. Nahezu alle neuen Anwendungen werden mit .NET Core entwickelt.
Viele dieser .NET Core-Anwendungen sind stark frequentiert und verarbeiten Millionen von Nutzern und Transaktionen. Daher haben diese Anwendungen einen enormen Einfluss auf Ihr Unternehmen und sind deshalb von großer Bedeutung.
Die .NET Core-Anwendungen, die Skalierbarkeit benötigen, sind in der Regel Serveranwendungen, die eine große Anzahl von Transaktionen sehr schnell und mit extrem kurzen Antwortzeiten verarbeiten müssen. Viele dieser Anwendungen haben direkten Kundenkontakt und bearbeiten daher Kundenanfragen. Werden Kundenanfragen nicht schnell genug bearbeitet, entstehen dem Unternehmen hohe Kosten durch Umsatzeinbußen und den Verlust zufriedener Kunden.
Folgende .NET Core-Anwendungen erfordern Skalierbarkeit:
Interessanterweise verfügen alle oben genannten Anwendungen über sehr skalierbare Architekturen auf Anwendungsebene. Jeder von ihnen ermöglicht Ihnen eine lineare Skalierung, wenn Ihre Transaktionslast wächst, indem Sie weitere Server, VMs oder Containerinstanzen zusammen mit einem Load Balancer hinzufügen.
Trotz einer sehr skalierbaren Architektur auf Anwendungsebene stoßen .NET Core-Serveranwendungen heute auf erhebliche Skalierungsprobleme. Diese Probleme treten in verschiedenen Bereichen auf, wie zum Beispiel:
Der größte Engpass für alle stark frequentierten .NET Core-Anwendungen ist ihre Anwendungsdatenbank. Die meisten Anwendungen nutzen heute noch relationale Datenbanken wie SQL Server oder Oracle. Diese Datenbanken werden schnell zu Skalierungsengpässen, wenn die Transaktionslast dieser Anwendungen steigt. Dies gilt unabhängig davon, ob Sie SQL Server auf einer virtuellen Maschine oder Azure SQL-Datenbank verwenden.
Dies liegt daran, dass eine relationale Datenbank nicht wie eine NoSQL-Datenbank logisch partitioniert werden kann, sondern an einem einzigen physischen Ort verbleibt; selbst eine Partitionierung auf Spaltenebene entspricht nicht dem typischen NoSQL-Partitionierungsstil. Daher lässt sich die Transaktionskapazität der Datenbankebene nicht durch Hinzufügen weiterer Datenbankserver wie bei einer NoSQL-Datenbank erweitern.
Während Ihre Anwendungsschicht beispielsweise problemlos 10, 20, 30 oder mehr Anwendungsserver umfassen kann, wenn Ihre Transaktionslast zunimmt, kann Ihre Datenbankschicht überhaupt nicht in der gleichen Weise wachsen.
Aus all diesen Gründen wird Ihre relationale Datenbank zu einem Leistungsengpass für alle darin gespeicherten Daten (Anwendungsdaten oder andere Daten).
SQL Server hat In-Memory-Optimierungen eingeführt, um die Anzahl der Transaktionen pro Sekunde zu erhöhen. Oracle hat auch eine eigene Version von In-Memory-Tabellen bereitgestellt.
Während In-Memory-Optimierungen zu Leistungsverbesserungen führen, lösen sie nicht das Kernproblem der linearen Skalierbarkeit. In-Memory-Tabellen werden im Allgemeinen für schreibgeschützte Daten verwendet. Um eine schreibgeschützte Transaktionskapazität zu skalieren, müssen Sie auf High-End-Computern weitere Instanzen von SQL Server hinzufügen.
Auch für In-Memory-Tabellen gelten Einschränkungen hinsichtlich der Datengröße. Sie können keine großen Tabellen im Speicher ablegen, da die gesamte Tabelle im Speicher abgelegt werden muss. Und ihre Replikation auf andere SQL Server-Instanzen kann nur auf andere In-Memory-Tabellen und nicht auf eine richtige Datenbank erfolgen.
Zusammenfassend lässt sich sagen, dass diese In-Memory-Optimierungen in SQL Server- und Oracle-Datenbanken die Skalierungsanforderungen Ihrer .NET Core-Anwendung nicht vollständig erfüllen können.
Einer der Gründe für die Popularität von NoSQL-Datenbanken liegt in der effizienten Datenpartitionierung mittels Hash-basierter und anderer Algorithmen. Dadurch werden viele Skalierungsprobleme hinsichtlich der Transaktionskapazität gelöst, mit denen relationale Datenbanken wie SQL Server und Oracle konfrontiert sind.
Es gibt jedoch Gründe, warum NoSQL-Datenbanken nicht die ideale Lösung für diese Datenbankengpässe darstellen.
Die Lösung für alle oben genannten Probleme ist die Verwendung eines In-Memory Distributed Cache wie NCache in Ihrer .NET Core-Anwendungsbereitstellung. NCache ist ein Open-Source-Cache für .NET und .NET Core, der extrem schnell und linear skalierbar ist. Man kann ihn sich als verteilten In-Memory-Datenspeicher vorstellen. Die In-Memory-Architektur sorgt für extreme Geschwindigkeit, die verteilte Architektur für lineare Skalierbarkeit.
NCache ist linear skalierbar, da es einen TCP-Cluster kostengünstiger Cache-Server aufbaut (gleiche Konfiguration wie Ihre Web-App-Server, aber mit mehr Speicher) und die Speicher- und CPU-Ressourcen aller dieser Server in einer logischen Kapazität zusammenfasst. NCache Anschließend können Sie diesem Cluster zur Laufzeit Cache-Server hinzufügen, wenn Ihre Transaktionslast zunimmt. Und da NCache Da alles im Arbeitsspeicher stattfindet, ist es superschnell und bietet Ihnen Antwortzeiten im Submillisekundenbereich, die Sie von relationalen Datenbanken oder sogar NoSQL-Datenbanken nicht erwarten können.
Zusätzlich zur Bereitstellung linearer Skalierbarkeit bietet ein verteilter Cache z NCache repliziert Daten intelligent, sodass Ihre Leistung nicht beeinträchtigt wird und gleichzeitig Datenzuverlässigkeit gewährleistet wird, falls ein Cache-Server ausfällt.
NCache Ermöglicht die Skalierung Ihrer .NET Core-Anwendungen durch Folgendes:
Der größte Engpass bei .NET Core-Anwendungen ist die „Anwendungsdatenbank“. Das Schöne daran ist, dass NCache Im Gegensatz zu NoSQL-Datenbanken NCache fordert Sie nicht auf, die Nutzung Ihrer vorhandenen relationalen Datenbank einzustellen. Sie können weiterhin SQL Server, Azure SQL-Datenbank, Oracle usw. als Datenbank verwenden und dennoch eine lineare Skalierbarkeit erreichen NCache zusätzlich zu Ihrer relationalen Datenbank. Das ist weil NCache beseitigt alle Engpässe bei der Skalierbarkeit relationaler Datenbanken, da im Gegensatz zu Ihrer Datenbank NCache ist tatsächlich linear skalierbar.
Mit Application Data Caching können Sie Ihre Datenbankengpässe beseitigen. NCache ermöglicht es Ihnen, Anwendungsdaten zwischenzuspeichern und teure Datenbankfahrten zu reduzieren. Sie können davon ausgehen, dass 80–90 % des Datenbankdatenverkehrs dorthin umgeleitet werden NCache. Dies verringert den Druck auf Ihre Datenbank und ermöglicht eine schnellere Leistung sowie die Bewältigung größerer Transaktionslasten ohne Verlangsamung.
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.
Customer Load(string custId)
{
ICache cache = CacheManager.GetCache("myCache");
string key = "Customer:CustomerID:" + custId;
Customer cust = cache.Get<Customer>(key);
if (cust == null)
{
// Item not in cache so load from db
LoadCustomerFromDb(cust);
// Add item to cache for future reference
cache.Add(key, cust);
}
return cust;
}
Abbildung 3: Verwendung des verteilten In-Memory-Cache für das App-Daten-Caching
Ein weiterer möglicher Engpass entsteht, wenn Sie Ihre ASP.NET Core-Sitzungen in SQL Server oder einem separaten MemoryCache speichern. Beide Optionen weisen erhebliche Einschränkungen hinsichtlich Leistung und Skalierbarkeit auf. Die Speicherung in SQL Server ist für ASP.NET Core-Sitzungen ungeeignet und wird, ähnlich wie bei Anwendungsdaten, schnell zum Flaschenhals.
NCache ist ein hervorragender Ort zum Speichern Ihrer ASP.NET Core Sessions, da es viel schneller und skalierbarer ist als andere Speicheroptionen. NCache Es ist schneller, da es im Arbeitsspeicher arbeitet und eine Key-Value-Schnittstelle bereitstellt, wobei der Wert ein „Objekt“ ist, was eine ASP.NET Core-Session ist. Außerdem ist es skalierbar, da es sich um einen verteilten Cache handelt.
Und, NCache Zudem werden ASP.NET Core-Sitzungen durch die ausgefeilten Caching-Topologien intelligent repliziert, sodass selbst bei Ausfall eines Cache-Servers keine Sitzungsdaten verloren gehen. Diese Replikation ist notwendig, weil NCache Stellt einen In-Memory-Speicher bereit und der Speicher verletzt den Speicher.
NCache beschleunigt außerdem die Serialisierung der ASP.NET Core Session, die erforderlich ist, bevor sie außerhalb des Prozesses gespeichert werden kann. NCache Dies geschieht durch die Verwendung der Funktion „Dynamische kompakte Serialisierung“, die zehnmal schneller ist als die reguläre Serialisierung von .NET und .NET Core. Diese Funktion kann ohne Codeänderungen genutzt werden.
Sie können verwenden NCache als Ihren ASP.NET Core Session-Speicher auf zwei Arten.
Nachfolgend finden Sie ein Beispiel, wie Sie Ihre ASP.NET Core-Anwendung für die Verwendung konfigurieren können. NCache Sitzungsanbieter:
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
// Specify NCache as the session provider
services.AddNCacheSession(Configuration.GetSection("NCacheSettings"));
...
}
public void Configure(IApplicationBuilder app, ...)
{
// select NCache session provider for ASP.NET Core
app.UseNCacheSession();
...
}
}
Abbildung 4: Plug-in NCache als ASP.NET Core-Sitzungen
ASP.NET Core-Anwendungen, die ansonsten dynamische Inhalte aufweisen, stoßen auf Situationen, in denen sich der Inhalt oder die Antwort einiger Seiten über mehrere Anfragen hinweg nicht ändert. Diese Seiten müssen jedoch bei jeder Anfrage neu ausgeführt werden. Dies belastet die Ressourcen des Webservers und alle Ebenen der Anwendung unnötig. Infolgedessen entstehen Leistungsengpässe, und die Skalierbarkeit der Anwendung wird eingeschränkt.
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
// Turn on ASP.NET Core Response Cache with IDistributedCache
services.AddResponseCaching();
// Select NCache as IDistributedCache provider
services.AddNCacheDistributedCache(Configuration.GetSection("NCacheSettings"));
...
}
}
Abbildung 5: Plug-in NCache als ASP.NET Core Response Cache Middleware
Um den Mehraufwand bei wiederholter Seitenausführung zu reduzieren, wenn sich die Seitenantwort nicht ändert, bietet ASP.NET Core einen Mechanismus zum Zwischenspeichern von Seitenantworten namens ASP.NET Response Cache Middleware. NCache hat die IDistributedCache-Schnittstelle in ASP.NET Core implementiert, wodurch Sie nahtlos einbinden können NCache als Ihre ASP.NET Core Response Cache Middleware.
So können Sie verwenden NCache Um die Antworten von ASP.NET Core-Seiten für einen bestimmten Zeitraum zwischenzuspeichern, sodass beim nächsten Aufruf derselben Seite mit denselben Parametern diese zwischengespeicherte Antwort zurückgegeben werden kann, anstatt die gesamte Seite erneut auszuführen, finden Sie unten ein Codebeispiel zur Konfiguration. NCache als Ihre ASP.NET Core Response Cache Middleware.
Wenn Ihre ASP.NET Core-Anwendung eine Echtzeit-Webanwendung ist, verwendet sie höchstwahrscheinlich ASP.NET Core SignalR, um dieses Echtzeitverhalten zu realisieren. Echtzeit-Webanwendungen senden häufige Aktualisierungen vom Server an den Client. Beispiele für solche Anwendungen sind Spiele, Auktionsplattformen, Abstimmungssysteme, soziale Netzwerke usw.
Läuft Ihre ASP.NET Core-Anwendung in einer Load-Balancing-Umgebung mit mehreren Servern, benötigt sie einen ASP.NET Core SignalR Backplane-Provider, um Ereignisse zwischen den Webservern zu verteilen. Dieser Backplane muss skalierbar sein. Andernfalls stößt Ihre ASP.NET Core SignalR-Anwendung an ihre Leistungsgrenzen.
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
// Specify NCache as the ASP.NET Core SignalR Backplane
services.AddSignalR().AddNCache(ncacheOptions =>
{ ncacheOptions.CacheName = "myPartitionedCache"; });
...
}
public void Configure(IApplicationBuilder app, ...)
{
// Use SignalR in ASP.NET Core
app.UseSignalR(config => { config.MapHub<MessageHub>("/messages"); });
...
}
}
Abbildung 6: Plug-in NCache als ASP.NET Core SignalR Backplane Provider
NCache hat einen ASP.NET Core SignalR Backplane-Provider implementiert. NCacheDer ASP.NET Core SignalR Backplane-Provider nutzt die Pub/Sub-Messaging-Funktionen von NCache Diese sind extrem schnell, da sie vollständig im Arbeitsspeicher verarbeitet werden. Dadurch kann Ihre ASP.NET Core SignalR-Anwendung die SignalR-Ereignisweiterleitung zwischen allen Webservern und somit auch zu den Clients beschleunigen.
Und dadurch ist Ihre Echtzeit-Webanwendung reaktionsfähiger bei der Bereitstellung dieser häufigen Updates für die Clients. Und Sie können die Anzahl der Clients kontinuierlich erhöhen und auch weitere Webserver hinzufügen, ohne Leistungsengpässe befürchten zu müssen.
Wenn Ihre .NET Core-Anwendung Pub/Sub-Messaging oder Ereignisse benötigt, verwendet sie höchstwahrscheinlich eine Pub/Sub-Messaging-Plattform, die nicht vollständig im Arbeitsspeicher arbeitet, sondern alle Nachrichten auf der Festplatte speichert. Dies kann leicht zu einem Leistungsengpass führen, insbesondere bei Anwendungen mit hohem Transaktionsvolumen.
NCache Bietet außerdem ein Pub/Sub-Messaging, das superschnell ist, da es vollständig im Speicher läuft. Und es repliziert alle Nachrichten an andere NCache Server, um sicherzustellen, dass es beim Ausfall eines Servers nicht zu Datenverlusten kommt.
Wenn Ihre .NET Core-Anwendung also Folgendes verwendet NCache Als Pub/Sub-Messaging-Plattform wird es eine superschnelle Leistung und lineare Skalierbarkeit erleben NCache selbst ist linear skalierbar.
Nachfolgend finden Sie ein Beispiel dafür, wie Sie Pub/Sub Messaging verwenden können, das von bereitgestellt wird NCache in Ihrer .NET Core-Anwendung.
private void PublishMessage (string topicName)
{
ITopic topic = _cache.MessagingService.GetTopic(topicName);
Order order = Order.GenerateOrder<Order>();
// Publish message containing "order" with expiry
Message message = new Message(order, new TimeSpan(0, 0, 15));
topic.Publish(message, DeliveryOption.All, true);
}
private ITopicSubscription SubscribeMessage (string topicName)
{
ITopic topic = _cache.MessagingService.GetTopic(topicName);
// Subscribes to the topic. Message delivered to MessageReceivedCallback
return topic.CreateSubscription(MessageReceivedCallback);
}
static void MessageReceivedCallback(object sender, MessageEventArgs args) { ... }
Abbildung 7: Verwendung von Pub/Sub-Messaging in .NET Core-Anwendungen
Der größte Skalierungsengpass, den Ihre .NET Core-Anwendung beseitigen muss, liegt in der Anwendungsdatenbank. Hier können Ihre Anwendungen durch Daten-Caching eine hohe Leistung und lineare Skalierbarkeit erreichen. Der Grund dafür ist einfach: Die meisten .NET Core-Anwendungen greifen ständig auf große Datenmengen in der Datenbank zu.
Wenn es um das Zwischenspeichern von Anwendungsdaten geht, besteht die größte Angst der Menschen darin, dass der Cache veraltet ist, d. h. er enthält eine ältere Version der Daten, die bereits von einem anderen Benutzer oder einer anderen Anwendung in der Datenbank geändert wurde.
Diese Angst, dass ein Cache veraltet, ist so groß, dass die meisten Menschen nur schreibgeschützte oder statische Daten (Referenzdaten) zwischenspeichern. Diese schreibgeschützten Daten machen jedoch nur 20 % der gesamten Daten in Form von Nachschlagetabellen und anderen Referenzdaten aus. Der Großteil der Daten in der Datenbank sind Transaktionsdaten, einschließlich Kunden, Konten, Aktivitäten usw. Und wenn Sie diese Transaktionsdaten nicht zwischenspeichern, profitieren Sie nicht vollständig vom Caching.
Der wahre Vorteil des Caching liegt also darin, dass Sie alle Arten von Daten zwischenspeichern können, ohne befürchten zu müssen, dass das Caching veraltet ist. NCache bietet eine Vielzahl von Funktionen, um dieses Problem zu lösen.
Der effektivste Weg, Ihren Cache auf dem neuesten Stand zu halten, besteht darin, ihn immer mit Ihrer Datenbank zu synchronisieren. NCache können Sie dies wie folgt für eine Vielzahl von Datenbanken tun:
Wenn Sie Ihren Cache mit SQL Server synchronisieren, fragen Sie NCache um sich als Client von SQL Server zu registrieren und dann einen SqlDependency-Aufruf zusammen mit einem auf SQL-Abfragen basierenden Datensatz auszugeben. Wenn der SQL Server dann Änderungen in diesem Datensatz erkennt, benachrichtigt er ihn NCache darüber
private static void CreateSqlDependency (Product product)
{
string connectionString = "Data Source=localhost;Database=northwind;...";
// SQL stmt on which the SQL Dependency is created in SQL Server
string sqlStmt = "SELECT ProductID, ProductName, QuantityPerUnit, UnitPrice " +
"FROM dbo.PRODUCTS WHERE ProductID = " + product.Id;
CacheDependency sqlDependency = new SqlCacheDependency(connectionString, sqlStmt);
CacheItem cacheItem = new CacheItem(product) { Dependency = sqlDependency };
string key = "Product:ProductId:" + product.Id; ;
cache.Add(key, cacheItem);
}
Abbildung 8: Verwenden von SqlDependency zum Synchronisieren des Caches mit SQL Server
Dann, NCache Entfernt dieses Element aus dem Cache, sodass die Anwendung das nächste Mal, wenn sie es benötigt, die neueste Kopie aus der Datenbank abrufen muss. Wenn Sie den Read-through-Handler verwenden (siehe unten), dann NCache kann die neueste Kopie auch automatisch für Sie aus der Datenbank laden. Unten finden Sie ein Beispiel dafür, wie Sie SqlDependency verwenden können, um Ihren Cache mit SQL Server zu synchronisieren.
Read-through-Cache ist ein Cache, der Daten aus Ihrer Datenbank lesen kann, indem er einen Readthrough-Handler aufruft, den Sie entwickelt und dem Cache bereitgestellt haben. Ebenso ist ein Write-through-Cache in der Lage, Datenänderungen in Ihre Datenbank zu schreiben, indem er einen Write-through-Handler aufruft, den Sie entwickelt und dem Cache bereitgestellt haben. Der Write-Behind-Cache ist dasselbe wie der Write-Through-Cache, mit der Ausnahme, dass die Datenbankaktualisierungen asynchron erfolgen.
Read-through, Write-through und Write-behind bieten viele Vorteile für Ihre .NET Core-Anwendungen, darunter:
Nachfolgend finden Sie ein Beispiel dafür, wie Sie Read-through mit verwenden können NCache.
// Read through handler for SQL Server
public class SqlReadThruProvider : Runtime.DatasourceProviders.IReadThruProvider
{
public void Init(IDictionary parameters, string cacheId) {}
public void Dispose() {}
// Get object from the database/data-source based on the key
public ProviderCacheItem LoadFromSource(string key) {}
// Bulk-Get objects from the database/data-source based on the keys
public IDictionary<string, ProviderCacheItem> LoadFromSource(ICollection<string> keys)
{}
}
Abbildung 9: Verwendung des Read-through-Handlers mit NCache
Sobald Sie mit dem Zwischenspeichern aller Daten vertraut sind, können Sie damit beginnen, viele Daten in einem verteilten Cache abzulegen. Hier können Sie mit einem weiteren besonderen Problem konfrontiert werden: Wie Sie Ihre Daten schnell und einfach finden können. Da es sich bei den meisten verteilten Caches um Schlüsselwertspeicher handelt, wird es sehr schwierig, den Überblick über alle Ihre Daten allein über Schlüssel zu behalten.
Das ist wo NCache bietet Ihnen verschiedene Möglichkeiten, schnell Daten aus Ihrem Cache zu finden. Beispiele beinhalten:
Nachfolgend finden Sie ein Beispiel dafür, wie Sie LINQ-basierte Abfragen verwenden können NCache.
// Search the cache based on object attributes by using LINQ
IQueryable>Product< products = new NCacheQuery<Product>(_cache);
var result = from product in products
where product.Id > 10
select product;
if (result != null)
{
foreach (Product p in result1)
{
// Process each “product” fetched from the database
Console.WriteLine("ProductID : " + p.Id);
}
}
Abbildung 10: Verwenden von LINQ-Abfragen mit NCache
Stark frequentierte .NET Core-Anwendungen dürfen nicht ausfallen, insbesondere nicht zu Spitzenzeiten. Für diese Anwendungsarten gibt es drei wichtige Architekturziele, die ein guter verteilter In-Memory-Cache erfüllen sollte. NCache erfüllt.
Lassen Sie mich die einzelnen Punkte unten erklären.
NCache stellt einen Client-Cache bereit, bei dem es sich um einen lokalen Cache ganz in der Nähe Ihrer Anwendung handelt. Es kann sich entweder um InProc (d. h. es befindet sich in Ihrem Anwendungsprozess) oder um lokales OutProc handeln. In jedem Fall bietet es einen sehr schnellen Zugriff auf eine Teilmenge der zwischengespeicherten Daten, die Ihre Anwendung auf diesem App-Server zu diesem Zeitpunkt benötigt. Gleichzeitig bleibt der Client-Cache mit der Caching-Ebene synchronisiert, sodass alle Daten, die von anderen Benutzern oder Anwendungen in der Caching-Ebene geändert werden, sofort an den Client-Cache weitergegeben werden. Der Client ermöglicht Ihnen InProc-Geschwindigkeit und ist gleichzeitig Teil einer sehr skalierbaren Caching-Ebene.
Eines der wichtigsten architektonischen Ziele von NCache besteht darin, durch seine Caching-Topologien eine lineare Skalierbarkeit mit Datenzuverlässigkeit zu erreichen. Hier sind einige NCache Caching-Topologien die dazu beitragen, diese beiden Ziele zu erreichen.
Eines der wichtigsten architektonischen Ziele von NCache besteht darin, eine hohe Verfügbarkeit und Cache-Elastizität zu erreichen. Dies geschieht durch die folgenden architektonischen Fähigkeiten:
© Copyright Alachisoft 2002 - Alle Rechte vorbehalten NCache ist eine eingetragene Marke der Diyatech Corp.