.NET Core und ASP.NET Core erfreuen sich aufgrund ihres einfachen Designs, ihres geringen Gewichts, ihrer Open Source-Qualität und ihrer Lauffähigkeit sowohl unter Windows als auch unter Linux zunehmender Beliebtheit. Dadurch werden auch viele bestehende Anwendungen verschoben .NET Core von dem .NET Framework. Fast alle neuen Anwendungen werden in entwickelt .NET Core.
Viele davon .NET Core Anwendungen sind von Natur aus stark frequentiert und bedienen Millionen von Benutzern und Transaktionen. Daher haben diese Anwendungen einen enormen Einfluss auf Ihr Unternehmen und sind daher sehr wichtig.
Das .NET Core Anwendungen, die normalerweise Skalierbarkeit erfordern, sind Serveranwendungen, die viele Transaktionen sehr schnell und mit sehr kurzen Antwortzeiten verarbeiten müssen. Viele dieser Anwendungen sind kundenorientiert, das heißt, sie verarbeiten Kundenanfragen. Wenn sie Kundenanfragen nicht schnell erfüllen, sind die Kosten für das Unternehmen in Form von Umsatzeinbußen und dem Verlust zufriedener Kunden hoch.
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.
Doch trotz einer sehr skalierbaren Architektur auf der Anwendungsebene .NET Core Serveranwendungen sind heute mit großen Skalierbarkeitsengpässen konfrontiert. Diese Engpässe treten in verschiedenen Bereichen auf, wie zum Beispiel:
Der größte Engpass für alle mit hohem Verkehrsaufkommen .NET Core Anwendungen ist ihre Anwendungsdatenbank. Die meisten Anwendungen nutzen heute noch eine relationale Datenbank wie SQL Server oder Oracle. Diese Datenbanken werden schnell zu Skalierbarkeitsengpässen, wenn Sie die Transaktionslast dieser Anwendungen erhöhen. Dies gilt unabhängig davon, ob Sie SQL Server auf einer VM oder einer Azure SQL-Datenbank verwenden.
Dies liegt daran, dass eine relationale Datenbank nicht wie eine logisch partitioniert werden kann NoSQL database und bleibt stattdessen an einem physischen Ort; Selbst eine gewisse Partitionierung auf Spaltenebene ist nichts anderes als eine echte NoSQL Stilpartition. Daher können Sie die Transaktionskapazität der Datenbankebene nicht durch das Hinzufügen weiterer Datenbankserver erhöhen, wie dies bei einem der Fall ist NoSQL database.
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 nicht in der Lage sind, Ihre Probleme vollständig zu lösen .NET Core Skalierbarkeitsanforderungen der Anwendung.
Einer der Gründe NoSQL databases sind populär geworden, weil sie eine ordnungsgemäße Partitionierung von Daten basierend auf Hash-basierten und anderen Algorithmen ermöglichen. Dies löst viele der Probleme der Skalierbarkeit der Transaktionskapazität, mit denen relationale Datenbanken wie SQL Server und Oracle konfrontiert sind.
Aber es gibt Gründe NoSQL databases sind nicht die ideale Lösung für diese Datenbankengpässe.
Die Lösung für alle oben genannten Probleme ist die Verwendung eines In-Memory Distributed Cache wie NCache in Ihrem .NET Core Anwendungsbereitstellung. NCache ist ein verteilter Open-Source-Cache für .NET und .NET Core Das ist extrem schnell und linear skalierbar. Stellen Sie sich das als einen In-Memory-Datenspeicher vor, der ebenfalls verteilt ist. Durch die In-Memory-Speicherung ist es extrem schnell und durch die Verteilung linear skalierbar.
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 ist vollständig speicherintern, superschnell und bietet Reaktionszeiten von weniger als einer Millisekunde, die Sie von Ihren relationalen Datenbanken oder gar nicht erwarten können NoSQL databases.
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 Ihnen die Skalierung Ihrer .NET Core Bewerbungen über Folgendes:
Der größte Engpass, mit dem wir konfrontiert sind .NET Core Anwendungen ist die „Anwendungsdatenbank“. Das Schöne daran NCache ist das anders? NoSQL databases, 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 Ihr ASP speichern.NET Core Sitzungen in SQL Server oder eigenständigem MemoryCache. Bei beiden Optionen bestehen große Einschränkungen hinsichtlich Leistung und Skalierbarkeit. SQL Server-Speicher ist für ASP nicht geeignet.NET Core Sitzungen und wird schnell zu einem Engpass, genau wie bei Anwendungsdaten.
NCache ist ein großartiger Ort, um Ihr ASP zu speichern.NET Core Sitzungen, weil es viel schneller und skalierbarer ist als andere Speicheroptionen. NCache ist schneller, da es sich im Arbeitsspeicher befindet und eine Schlüsselwertschnittstelle bereitstellt, wobei der Wert ein „Objekt“ ist, das ein ASP ist.NET Core Sitzung ist. Und es ist skalierbar, da es sich um einen verteilten Cache handelt.
Und, NCache repliziert auch ASP intelligent.NET Core Sitzungen über seine umfangreichen Caching-Topologien, sodass selbst bei einem Ausfall eines Cache-Servers kein Sitzungsdatenverlust auftritt. Diese Replikation ist erforderlich, weil NCache Stellt einen In-Memory-Speicher bereit und der Speicher verletzt den Speicher.
NCache beschleunigt auch Ihre Serialisierung des ASP.NET Core Sitzung, die erforderlich ist, bevor sie außerhalb des Prozesses gespeichert werden kann. NCache Dies geschieht durch die Verwendung der Dynamic Compact Serialization-Funktion, die zehnmal schneller ist als normales .NET und .NET Core Serialisierung. Sie können diese Funktion verwenden, ohne Codeänderungen vorzunehmen.
Sie können verwenden NCache als Ihr ASP.NET Core Sitzungsspeicher auf zwei Arten.
Nachfolgend finden Sie ein Beispiel dafür, wie Sie Ihren ASP konfigurieren können.NET Core Anwendung zu verwenden 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 Sessions
ASP.NET Core Anwendungen, die ansonsten einen recht dynamischen Inhalt haben, sind mit Situationen konfrontiert, in denen sich der Inhalt oder die Antwort einiger ihrer Seiten über mehrere Anfragen hinweg nicht ändert. Diese Seiten müssen jedoch immer noch bei jeder Anforderung ausgeführt werden. Dies führt zu einer unnötigen Belastung der Webserver-Ressourcen und aller Ebenen dieser Anwendung. Dadurch kommt es auch zu Leistungsengpässen 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 Antwort-Cache-Middleware
ASP.NET Core hat einen Seitenantwort-Caching-Mechanismus namens ASP.NET Response Cache Middleware bereitgestellt. Und, NCache hat die IDistributedCache-Schnittstelle in ASP implementiert.NET Core Dadurch können Sie nahtlos einstecken NCache als Ihr ASP.NET Core Antwort-Cache-Middleware.
So können Sie verwenden NCache um ASP zwischenzuspeichern.NET Core Seitenantworten für einen bestimmten Zeitraum, sodass beim nächsten Aufruf derselben Seite mit denselben Parametern diese zwischengespeicherte Antwort neu abgestimmt werden kann, anstatt die gesamte Seite erneut auszuführen. Nachfolgend finden Sie das Codebeispiel zur Konfiguration NCache als Ihr ASP.NET Core Antwort-Cache-Middleware.
Wenn Ihr ASP.NET Core Wenn es sich bei der Anwendung um eine Echtzeit-Webanwendung handelt, verwendet sie höchstwahrscheinlich ASP.NET Core SignalR für die Bereitstellung dieses Echtzeitverhaltens. Echtzeit-Webanwendungen stellen Hochfrequenzaktualisierungen vom Server zum Client bereit. Beispiele für solche Anwendungen sind Spiele, Auktionen, Abstimmungen, soziale Netzwerke usw.
Wenn Ihr ASP.NET Core Wenn die Anwendung in einer Umgebung mit mehreren Servern mit Lastausgleich ausgeführt wird, muss sie einen ASP verwenden.NET Core SignalR Backplane Anbieter, um Ereignisse über mehrere Webserver hinweg zu teilen. Und diese Backplane muss skalierbar sein. Ansonsten Ihr ASP.NET Core Bei der SignalR-Anwendung treten Leistungsengpässe auf.
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 implementiert.NET Core SignalR Backplane Anbieter. NCacheist ASP.NET Core SignalR Backplane Der Anbieter nutzt Pub/Sub-Messaging-Funktionen von NCache die superschnell sind, da sie vollständig im Speicher gespeichert sind. Dies ermöglicht Ihrem ASP.NET Core SignalR-Anwendung zur Beschleunigung der SignalR-Ereignisweitergabe zwischen allen Webservern und damit an die Clients.
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 dein .NET Core Wenn die Anwendung Pub/Sub-Messaging oder -Ereignisse verwenden muss, verwendet sie höchstwahrscheinlich eine Pub/Sub-Messaging-Plattform, die nicht vollständig In-Memory ist und stattdessen alle Nachrichten auf der Festplatte speichert. Dies kann daher leicht zu einem Leistungsengpass führen, wenn Ihre Anwendung sehr transaktionsstark ist.
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.
Deshalb, wenn Ihr .NET Core Anwendung nutzt 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 Ihrem .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: Verwenden von Pub/Sub-Nachrichten in .NET Core Apps
Der größte Skalierbarkeitsengpass, den Sie haben .NET Core Die Anwendung muss aus der Anwendungsdatenbank entfernt werden. In diesem Bereich können Ihre Anwendungen durch Anwendungsdaten-Caching eine hohe Leistung und lineare Skalierbarkeit erreichen. Der Grund dafür ist einfach. Am meisten .NET Core Anwendungen verarbeiten viele Daten hin und her aus der Datenbank.
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 Ihnen viele Vorteile .NET Core Anwendungen einschließlich:
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
Viel Verkehr .NET Core Anwendungen können es sich nicht leisten, auszufallen, insbesondere während der Spitzenzeiten. Für diese Art von Anwendungen gibt es drei wirklich wichtige Architekturziele, die einem guten InMemory Distributed Cache entsprechen 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: