In diesem Artikel gehen wir durch, wie eine verteilte Caching-Lösung die Gesamtleistung und den Durchsatz Ihrer auf Microservices basierenden Anwendung drastisch verbessern kann.
In einer typischen Microservice-basierten Anwendung arbeiten mehrere Microservices zusammen, bleiben aber lose gekoppelt und skalierbar. Die Anwendung verfügt über Dienste, die erforderlich sind, um Kerngeschäftsanforderungen zu erfüllen, wie z. B. das Verfolgen und Verarbeiten kritischer Geschäftsdaten. Es gibt auch zusätzliche dedizierte Microservices, die Identität und Authentifizierung, Zustands- und Lastüberwachung handhaben und als API-Gateways dienen.
Ein Hauptmerkmal einer solchen Anwendung besteht darin, dass jeder Microservice unabhängig unter Verwendung eines beliebigen Technologie-Stacks entworfen, entwickelt und bereitgestellt werden kann. Da jeder Microservice eine eigenständige autonome App ist, behält er auch seinen separaten persistenten Speicher, sei es eine relationale Datenbank, a NoSQL DB oder sogar ein älteres Dateispeichersystem. Dadurch können die einzelnen Microservices unabhängig voneinander skalieren und Änderungen an der Infrastruktur in Echtzeit viel besser beherrschbar werden.
NCache Details Microservices mit NCache Skalieren Sie Pub/Sub in Microservices
Warum benötigt Ihr Microservice NCache?
Es gibt Fälle, in denen es bei erhöhten Transaktionen auf der Anwendung immer noch zu Engpässen kommt. Dies ist vor allem in Architekturen üblich, in denen Microservices Daten in relationalen Datenbanken speichern, die kein Scale-out zulassen. In solchen Situationen löst die horizontale Skalierung des Microservices durch die Bereitstellung weiterer Instanzen davon keine Lösung.
Um diesen Problemen entgegenzuwirken, können Sie nahtlos einführen NCache als Ihr verteilter Cache auf der Caching-Ebene zwischen Ihren Microservices und den Datenspeichern. NCache Hilft auch als skalierbarer In-Memory-Publisher/Subscriber-Messaging-Broker, um asynchrone Kommunikation zwischen Microservices zu ermöglichen.
Skalierbarkeit durch Pub/Sub
Die Kommunikation von Microservices wird häufig mithilfe des Publisher/Subscriber-Modells implementiert, das die Nachrichtenübermittlung zwischen Microservices ermöglicht und diese gleichzeitig lose gekoppelt hält. In jener Hinsicht, NCache dient als speicherinterner skalierbarer Pub/Sub-Messaging-Broker, über den alle Microservices, aus denen die Anwendung besteht, Ereignisse veröffentlichen und abonnieren können. Die Skalierbarkeits- und Zuverlässigkeitsfunktion von NCache Clustering werden automatisch übersetzt, wenn wir zu Pub/Sub kommen. Erfahren Sie mehr über NCache als Message Broker im Microservices-Umfeld über unseren Blog auf Skalierung der .NET Microservices-Kommunikation mit In-Memory Pub/Sub.
NCache Details Pub/Sub-Messaging in NCache Skalieren Sie Pub/Sub in Microservices
Skalierbarkeit durch Caching
NCache bietet Echtzeit-Skalierbarkeit, sodass Sie Ihrem laufenden Cache-Cluster so viele Serverknoten hinzufügen können, wie Sie möchten, ohne dass es zu Anwendungsausfallzeiten kommt. Verwenden NCache verbessert nicht nur die Gesamtleistung der einzelnen Microservices, indem es als schneller In-Memory-Speicher fungiert, sondern ermöglicht durch seine Clustering-Architektur auch eine deutliche Erhöhung der Reaktionszeit und Verfügbarkeit der Anwendung. Dies gilt insbesondere bei Workflows mit Dutzenden von Microservices, die über mehrere Hosts verteilt sind.
So wird es genutzt NCache für Daten-Caching?
Mit der NCache Wenn ein Microservice Daten benötigt, überprüft er stattdessen zuerst den Cache, anstatt jedes Mal direkt auf die Datenbank zuzugreifen. Da die Daten, auf die am häufigsten zugegriffen wird, normalerweise einen kleinen Teil der gesamten im Datenspeicher verfügbaren Daten ausmachen, reduziert die Tatsache, dass diese Daten bereits zwischengespeichert und zur Verwendung verfügbar sind, die datenbankbezogene Latenz erheblich und verringert die Belastung der Datenbank seit den meisten der Datenanfragen werden vom Cache selbst bedient.
Angesichts der Tatsache, dass eine auf Microservices basierende Anwendung von Natur aus langsamer ist, als wenn sie mit einer monolithischen Designstruktur erstellt wird, ist es klar, dass Sie den Geschwindigkeitsgewinn von benötigen NCache. NCache, auf Microservice-Ebene, kann dazu beitragen, die Leistungsfähigkeit einer Microservices-Architektur zu nutzen und gleichzeitig die Gesamtlatenz zu verringern, die bei langen Transaktionen beobachtet wird, die mehrere nacheinander arbeitende Dienste umfassen.
NCache verfügt über mehrere sofort einsatzbereite Funktionen, die eine feinkörnige Kontrolle über Caching-Vorgänge ermöglichen. Zu diesen Vorgängen gehören das Erzwingen von Cache-Konsistenz mithilfe von Ablauf- und Datenbanksynchronisierung sowie umfangreiche APIs, die bei der Implementierung von Cache-Aside- und Cache-Through-Funktionen mithilfe von Backing-Source-Anbietern helfen. NCache bietet auch SQL-ähnliche Abfragevorgänge für den Cache mithilfe von SQL-Abfragen und dient als Caching-Anbieter für Object Relational Mapper (ORM) wie EF Core.
Um loszulegen NCache In Ihrer auf Microservices basierenden Anwendung müssen Sie zunächst Dienste konfigurieren. Dadurch erhalten Sie die erforderlichen Informationen, die Ihre Microservices benötigen, um sie verwenden zu können NCache. Ein Überblick darüber, wie Sie einen gegenseitigen Kontext zwischen erstellen können NCache und Ihre Microservices-basierte Anwendung wird unten angezeigt:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
public IServiceProvider ConfigureServices(IServiceCollection services) { //Add additional code here services.AddDbContext<CatalogContext>(options => { var cacheID = configuration["CatalogCache"]; if (string.IsNullOrEmpty(cacheID)) cacheID = "CatalogCache"; NCacheConfiguration.Configure(cacheID, DependencyType.Other); // Changing default behavior when client evaluation occurs to throw. // Default in EF Core would be to log a warning when client evaluation is performed. options.ConfigureWarnings(warnings => warnings.Throw(RelationalEventId.QueryClientEvaluationWarning)); //Check Client vs. Server evaluation: https://docs.microsoft.com/en-us/ef/core/querying/client-eval }); var container = new ContainerBuilder(); container.Populate(services); return new AutofacServiceProvider(container.Build()); } |
Was Sie jetzt tun müssen, ist, einen Controller mit der Logik bereitzustellen, mit der er ein Element aus dem Cache abrufen kann, wenn er es dort findet. Und wenn nicht, holt der Controller das Element aus der Datenbank und speichert es im Cache. Die Implementierung eines solchen Controllers ist nachfolgend dargestellt:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
[Route("api/v1/[controller]")] [ApiController] public class CatalogController : ControllerBase { private readonly CatalogContext _catalogContext; private readonly CatalogSettings _settings; private readonly ICatalogIntegrationEventService _catalogIntegrationEventService; public CatalogController(CatalogContext context, IOptionsSnapshot<CatalogSettings> settings, ICatalogIntegrationEventService catalogIntegrationEventService) { _catalogContext = context ?? throw new ArgumentNullException(nameof(context)); _catalogIntegrationEventService = catalogIntegrationEventService ?? throw new ArgumentNullException(nameof(catalogIntegrationEventService)); _settings = settings.Value; } [HttpGet] [Route("items/{id:int}")] [ProducesResponseType((int)HttpStatusCode.NotFound)] [ProducesResponseType((int)HttpStatusCode.BadRequest)] [ProducesResponseType(typeof(CatalogItem), (int)HttpStatusCode.OK)] public async Task<ActionResult<CatalogItem>> ItemByIdAsync(int id) { if (id <= 0) { return BadRequest(); } CatalogItem item = null; var cache = _catalogContext.GetCache(); string catalogItemKey = "CatalogItem:" + id; //Getting item from cache item = cache.Get<CatalogItem>(catalogItemKey); if (item == null) { item = await _catalogContext.CatalogItems.SingleOrDefaultAsync(ci => ci.Id == id); cache.Insert(catalogItemKey, item); } // Your logic here if (item != null) return item; return NotFound(); } } |
NCache Details Microservices mit NCache
Lassen Sie uns ihre Details durchgehen, um die wahren Reize von kennenzulernen NCache bei Mikrodiensten.
Halten Sie den Cache immer frisch
Es gibt einen wichtigen Vorbehalt bei der Verwendung eines Caches, der damit zusammenhängt, dass der Cache im Vergleich zum Inhalt des zugrunde liegenden primären Datenspeichers „veraltete“ Daten speichert. Um sicherzustellen, dass jeder Mikrodienst aktuelle Daten aus seinem Cache erhält, müssen Sie die Cache-Daten regelmäßig aktualisieren. Glücklicherweise, NCache bietet Funktionen wie Datenbank Synchronisierung machen Ablauf um sicherzustellen, dass die Daten mit denen im primären Datenspeicher konsistent bleiben.
Sie können ein gewisses Maß an Synchronisierung des Caches mit dem Datenspeicher aufrechterhalten, indem Sie den zwischengespeicherten Elementen einfach ein Ablaufzeitintervall hinzufügen. Sobald es abgelaufen ist, NCache Entfernt das zwischengespeicherte Element, sodass nachfolgende Anforderungen für dieselben Informationen dazu führen, dass die aktualisierten Daten zwischengespeichert werden. NCache bietet sowohl Absolute und auch der Gleitend Ablaufstrategien und Sie können je nach der Vergänglichkeit der betreffenden Daten eine davon verwenden.
Als Beispiel zeigt das folgende Code-Snippet, wie einfach Sie ein absolutes Ablaufdatum für ein bestimmtes Cache-Element einführen können:
1 2 3 4 |
var cacheItem = new CacheItem(product); var expiration = new Expiration(ExpirationType.Absolute, TimeSpan.FromMinutes(5)); cacheItem.Expiration = expiration; cache.Insert(key, cacheItem); |
Um das gleitende Ablaufdatum zu verwenden, müssen Sie lediglich den ExpirationType als solchen ändern:
1 |
var expiration = new Expiration(ExpirationType.Sliding, TimeSpan.FromMinutes(5)); |
Eine Hauptanforderung beim Festlegen von Ablaufzeiten in einem beliebigen Cache, um die Konsistenz der Cache-Daten aufrechtzuerhalten, besteht darin, dass die festgelegten Ablaufzeiten der Geschwindigkeit entsprechen müssen, mit der sich das spezifische Datenelement auf der Seite des Datenspeichers ändert. Wenn Sie die Ablaufzeiten zu kurz einstellen, werden Daten möglicherweise unnötig entfernt und führen zu einer unnötigen und teuren Datenspeicherreise. wenn die Ablaufzeit zu lang ist, können veraltete Daten verwendet werden.
NCache Details Datenablauf in NCache
Das Finden der optimalen Werte für Ablaufzeiten erfordert daher eine gründliche Kenntnis der Datenzustandsänderungsmuster, was normalerweise nicht machbar ist. Wenn die Anforderungen an die Cachekonsistenz strenger werden, sind Datenbanksynchronisierungsstrategien der empfohlene Ansatz. NCache bietet diesbezüglich mehrere Strategien zur Datenbanksynchronisierung.
Mit diesen können Sie den Cache mit dem Datenspeicher synchronisieren, ohne auf die Datenzugriffsmuster der einzelnen Informationen eingehen zu müssen, wie dies bei der Verwendung von Expiration erforderlich ist. Wann immer es nun eine Änderung an diesem Element auf der Datenspeicherseite gibt, kann der Cache dieses Element dann automatisch ohne weitere Verzögerung entfernen.
Um dies in Aktion zu sehen, zeigt der folgende Codeausschnitt, wie Sie synchronisieren können NCache mit einer SQL Server-Datenbank durch Hinzufügen NCache SQL-Abhängigkeit auf die zwischengespeicherten Elemente.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
// Creating SQL Dependency string query = "SELECT ProductName, UnitPrice FROM dbo.Products WHERE CategoryID = 'Dairy';"; SqlCacheDependency sqlDependency = new SqlCacheDependency(connectionString, query); // Get orders that contain products with given category ID Order[] orders = FetchOrdersByProductCategoryID("Dairy"); foreach (var order in orders) { // Generate a unique cache key for this order string key = $"Order:ProductCategory-Dairy:{order.OrderID}"; // Create a new cacheitem and add sql dependency to it CacheItem item = new CacheItem(order); item.Dependency = sqlDependency; //Add cache item in the cache with SQL Dependency cache.Insert(key, item); } |
SQL-Abfrage im Cache
NCache bietet Ihren Microservices die Möglichkeit, indizierte Cache-Daten über einen SQL-ähnlichen Abfragemechanismus abzufragen. Dieses Merkmal erweist sich in Fällen als wertvoll, in denen die Werte der Schlüssel, gegen die die erforderlichen Informationen gespeichert sind, unbekannt sind. Dadurch werden auch viele der Cache-API-Aufrufe auf niedrigerer Ebene abstrahiert und Ihr Anwendungscode ist ziemlich verständlicher und wartungsfreundlicher. Diese Funktion erweist sich als einzigartig geeignet für Sie, wenn Sie mit SQL-ähnlichen Befehlen vertrauter sind.
Ein Beispiel-Code-Snippet, das die Verwendung von demonstriert NCache Die SQL-Abfragefunktion ist unten angegeben:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
string query = "SELECT * FROM FQN.Product WHERE ProductID > ?"; // Use QueryCommand for query execution var queryCommand = new QueryCommand(query); // Providing parameters for query queryCommand.Parameters.Add("ProductID",50000); // Executing QueryCommand through ICacheReader ICacheReader reader = cache.SearchService.ExecuteReader(queryCommand); // Check if the result set is not empty if (reader.FieldCount > 0) { while (reader.Read()) { string result = reader.GetValue<string>(1); // Perform operations using the retrieved keys } } else { // Null query result set retrieved } |
SQL-Abfragen können mit Abfrageindizes arbeiten, die NCache verteilte Datenstrukturen sowie Cache-Tags. Folgen Sie dem Link für weitere Informationen zu wie man das nutzen NCache SQL-Abfragefunktion.
NCache Details SQL-Abfrage in NCache
Durchlesen und Durchschreiben
Verwendung der NCache Anbieter von Datenquellen Funktion, Satz NCache aus Sicht des Microservices als einziger Eintrag in die Datenzugriffsschicht angezeigt; Benötigt ein Microservice Daten, muss er lediglich auf den Cache zugreifen. Der Cache stellt dann die Daten bereit, wenn sie im Cache verfügbar sind. Ist dies jedoch nicht der Fall, ruft er die Daten mithilfe eines Read-Thru-Handlers im Namen des Clients aus dem Datenspeicher ab, speichert sie im Cache und präsentiert sie dem Microservice.
In ähnlicher Weise muss ein Microservice durch die Verwendung eines Write-Through-Handlers nur einen Schreibvorgang (Hinzufügen, Aktualisieren, Löschen) im Cache ausführen, und der Cache führt dann den entsprechenden Schreibvorgang im Datenspeicher automatisch aus.
Darüber hinaus können Sie den Cache sogar zwingen, Daten direkt aus dem Datenspeicher abzurufen, unabhängig davon, ob der Cache eine möglicherweise veraltete Version davon enthält. Dies ist entscheidend, wenn der Microservice aktuelle Informationen benötigt und auf den zuvor erwähnten Cache-Konsistenzstrategien aufbaut.
Die Funktion des unterstützenden Datenquellenanbieters rationalisiert nicht nur Ihren Anwendungscode, sondern auch, wenn sie zusammen mit den vielen verwendet wird NCache Datenbank-Synchronisationsfunktionen verfügbar, der Cache wird mit automatisch neu geladenen frischen Daten gehalten, die für die Berechnung bereit sind.
Das folgende Code-Snippet hilft Ihnen dabei, Read-Thru in Ihren Microservices zu verwenden:
1 2 3 4 5 6 |
// Specify the readThruOptions for read through operations var readThruOptions = new ReadThruOptions(); readThruOptions.Mode = ReadMode.ReadThru; // Retrieve the data of the corresponding item with reads thru enabled Product data = cache.Get<Product>(key, readThruOptions); |
Auf ähnliche Weise können Sie Write-Through implementieren, indem Sie Folgendes verwenden:
1 2 3 4 5 6 |
// Enable write through for the cacheItem created var writeThruOptions = new WriteThruOptions(); writeThruOptions.Mode = WriteMode.WriteBehind; // Add item in the cache with write-behind cache.Insert(key, cacheItem, writeThruOptions); |
Ausführlichere Informationen zur Nutzung dieser Anbieter finden Sie in unserer Dokumentation unter Read-Through-Caching machen Write-Through-Caching.
NCache Details Datenquellenanbieter in NCache
EF-Core-Caching
Entity Framework (EF) Core ist ein leistungsstarker Object Relational Mapper (O/RM), der häufig in .NET-Unternehmensanwendungen verwendet wird. Und weil es so beliebt ist, NCache bietet eine EF Core-Caching-Anbieter Dadurch können Sie mithilfe von Erweiterungsmethoden wie FromCache nahtlos Caching in den EF Core-bezogenen Code einfügen. Dies ermöglicht EF Core-Entwicklern, die nicht genau damit vertraut sind NCache APIs, von denen Sie weiterhin profitieren können NCache.
Der folgende Code demonstriert die Benutzerfreundlichkeit der NCache EF Core-Cachinganbieter zum Einführen von Caching in Ihre vorhandene Microservice-Anwendungslogik.
1 2 3 4 5 6 7 8 9 |
var options = new CachingOptions { // To store the result as collection in cache StoreAs = StoreAs.Collection }; options.SetAbsoluteExpiration(DateTime.Now.AddMinutes(_settings.NCacheAbsoluteExpirationTime)); // Get items from cache. If not found, fetch from database and store in cache. item = await _catalogContext.CatalogItems.DeferredSingleOrDefault(ci => ci.Id == id).FromCacheAsync(options); |
Weitere Informationen zur EF Core Caching Provider API und wie sie Ihnen bei Ihrem Geschäftsfall helfen kann, finden Sie unter NCache EF-Core-Anbieter.
NCache Details EF -Kernspeicher in NCache
Alles zusammenfassen
Microservices werden mit der spezifischen Absicht entwickelt, autonom zu sein; dass Sie sie unabhängig von den anderen Microservices entwickeln, testen und bereitstellen können. Dies dient dazu, die gesamte Anwendung hoch skalierbar zu machen und offen für schnelle Continuous Integration/Continuous Deployment (CI/CD)-Prozesse zu sein.
Bei all den Vorteilen, die Microservices in Bezug auf Skalierbarkeit und schnelle Entwicklungslebenszyklen bieten, gibt es jedoch bestimmte Aspekte eines Anwendungsstapels, die Probleme verursachen. Zu diesen Aspekten gehören relationale Datenbanken, die kein Scale-out zulassen, das erforderlich ist, um mit erhöhter Last fertig zu werden, und hier ist eine verteilte Caching-Lösung sinnvoll NCache scheint.
NCache verfügt über zahlreiche sofort einsatzbereite Funktionen, die Sie dabei unterstützen, das Daten-Caching zu einer problemlosen und intuitiven Ergänzung Ihrer Microservices-Anwendung zu machen. Dazu gehören Datenbanksynchronisierung, Ablauf, EF Core-Caching, SQL-Abfrage und viel mehr.