Während meiner Karriere, in der ich APIs für verschiedene Projekte gearbeitet und entworfen habe, habe ich mir verschiedene Optimierungstechniken angeeignet. Die meisten sind theoretisch (in Bezug auf das Entwerfen von Systemen), aber ich habe meine 3 einfache API-Optimierungen der praktischen Strategien extrahiert, die die Leistung und die Benutzererfahrung verbessern.
Für jeden Tipp schauen wir uns empfohlene Bibliotheken an, die von der Community gut akzeptiert werden. Wenn Sie jedoch eine bestimmte Bibliothek verwenden, sollten Sie vorsichtig sein und sicherstellen, dass sie nicht bald aufgegeben wird. Eine Lösung besteht darin, die Bibliothek zu abstrahieren, damit Sie keine Kopfschmerzen haben, wenn Sie sie später ersetzen müssen.
Paginierung
Heutzutage sollte die Verwendung der Paginierung nicht mehr optional sein, da die meisten Systeme über viele Daten verfügen oder beabsichtigen, sich schnell zu füllen. Ich glaube, dass Sie alle, oder zumindest die meisten von Ihnen, versucht haben, eine Seite zu öffnen, auf der alle Benutzer auf einmal laden. Dann erfolgt die Filterung auf der Frontend-Seite?
Stellen Sie sich nun vor, dass ein Datensatz mit 10.000 Datensätzen aus der Datenbank geladen wird und der Browser den Filterteil durchführen muss. Der Computer wird langsamer und es wird schwierig sein, eine solche Website zu verwenden, und Sie werden am Ende frustrierte Benutzer haben.
Die allgemeine Praxis, die ich in den letzten 10 Jahren angewendet habe, ist, dass das Frontend nur als Präsentationselement des Systems dient, während das Backend die Daten sauber (strukturiert und optimiert) aufbereiten und dann bei Bedarf bereitstellen muss. Natürlich gibt es Ausnahmen, aber diese sollten marginal sein.
Wir können die Paginierung mit EF Core und LINQ implementieren, indem wir einfach Methoden wie and verwenden. Infolgedessen teilen wir die Daten in überschaubare Teile auf. Zum Beispiel: Skip Take
var pageData = dbContext.Items
.OrderBy(i => i.Id)
.Skip((pageNumber -1) * pageSize)
.Take(pageSize)
.ToList();
Wir haben also die Funktionalität erreicht, nur das abzurufen, was der Benutzer sucht und was er tatsächlich sehen kann.
Eine einfache Analogie wäre, als würde man nur eine Seite eines Buches zeigen, anstatt ihnen das ganze Buch zu geben.
Eine flexible Bibliothek für ASP.NET Core und MVC ist X.PagedList, die verschiedene Datenquellen unterstützt und Anpassungsoptionen bietet.
Caching und schneller Datenzugriff
Wenn wir Systeme entwickeln, die mit hohen Lasten umgehen sollen, dann müssen wir definitiv eine Caching-Strategie verwenden. Ich glaube, die meisten von Ihnen sind bereits mit dem Caching vertraut, daher werde ich hier nicht zu sehr ins Detail gehen. Aber ich werde einige Caching-Strategien behandeln. Es gibt verschiedene Caching-Strategien oder Entwurfsmuster. Im Folgenden werde ich jede einzelne kurz erklären und wie sie angewendet werden kann.
Cache-Aside-Muster
Dieses Cache-Muster kann erklärt werden, wenn wir uns vorstellen, dass wir Notizen für die Prüfung haben. Wenn wir die Notizen bereits an einem Ort haben, dann brauchen wir nicht zurückzugehen und im Buch nachzusehen. Wenn jedoch eine Notiz fehlt, können wir im Buch zurückblicken und sie dann aufschreiben. Das Ergebnis: Wir verschwenden keine Zeit mehr mit der Suche im Buch.
So können wir es in wenigen Schritten erklären:
- 1: Die Anwendung versucht zunächst, die Daten aus dem Cache zu lesen.
- arabische Ziffer: Wenn sich die Daten nicht im Cache befinden (Cache-Fehler), muss die Anwendung woanders suchen.
- 3: Die Anwendung liest dann die Daten aus der Hauptdatenbank.
- 4: Die Datenbank sendet die angeforderten Daten zurück an die Anwendung.
- 5: Die Anwendung speichert diese neu abgerufenen Daten im Cache und stellt sie für zukünftige Anforderungen zur Verfügung.
Unter dem Gesichtspunkt der Nutzung ist dieses Muster weit verbreitet und wird am häufigsten für Daten verwendet, die in der Regel gelesen und selten geändert werden. Auf der anderen Seite ist es möglich, Cache-Breaker-Techniken zu implementieren, die es ermöglichen, den Cache manuell zu aktualisieren. Anschließend wird eine Cache-Dauer (TTL) festgelegt, sodass sie automatisch gelöscht wird, wenn sie abläuft.
Read-Through-Pattern
Das Read-Through-Cache-Muster ist eine Art des Cachings, bei der die „Anwendung“ selbst das Caching nicht direkt verarbeitet. Nehmen wir an, wir haben einen spezialisierten Caching-Dienst, bei dem die Caching-Logik implementiert ist. Wenn ein Cache-Fehler auftritt, wechselt der Dienst zur Datenbank, um die Daten abzurufen und den Cache zu aktualisieren.
Ähnlich wie beim oben erläuterten Cache-Aside-Muster werden die Daten beim nächsten Zugriff auf den Dienst aus dem Cache bereitgestellt.
Wir können es so erklären:
- 1: Die Anwendung fordert Daten aus dem Cache (Redis) an.
- arabische Ziffer: Wenn sich die Daten nicht im Cache befinden, erkennt der Cachedienst, dass sie fehlen.
- 3: Der Cachedienst sendet automatisch eine Abfrage an die Datenbank und ruft die benötigten Daten ab.
- 4: Der Cache-Dienst empfängt Daten aus der Datenbank.
- 5: Der Cachedienst speichert die Daten im Cache und macht sie so für zukünftige Anforderungen bereit.
Write-Through-Muster
Wenn eine Anwendung Daten aktualisiert, schreibt sie diese zuerst in den Cache und dann in die Datenbank. Der Cache enthält also immer die aktuellsten Daten, da er mit jedem Eintrag synchronisiert wird.
Write-Behind-Muster (Write-Back) Die Daten werden zuerst in den Cache geschrieben und dann asynchron in der Datenbank gespeichert.
Reduziert im Allgemeinen die Belastung der Datenbank, da die Schreibvorgänge gruppiert und später ausgeführt werden, anstatt bei jedem Schreibvorgang.
Refresh-Ahead-Muster
Der Cache aktualisiert Daten automatisch vor dem Ablauf, um zukünftige Anforderungen zu antizipieren. So können die Daten im Vorfeld aufbereitet und bei Bedarf aktualisiert werden.
Sind sie die erste Wahl?
Nein, Cache-Aside ist die häufigste Wahl, da es einfach, flexibel und anpassbar ist. Write-Through, Write-Behind und Refresh-Ahead sind komplexer und werden nur in bestimmten Szenarien verwendet, in denen mehr Kontrolle über das Aktualisieren von Daten im Cache erforderlich ist.
Reduzieren Sie die Größe für eine schnellere Übertragung
Wenn wir unsere API zum Senden oder Empfangen großer Datenmengen benötigen, kann die für die Übertragung erforderliche Zeit die Leistung erheblich beeinträchtigen. Es ist logisch, dass die Daten in diesem Fall länger über das Netzwerk übertragen werden, was die Anwendung verlangsamen kann, was behoben werden kann, wenn wir im ersten Schritt die Paginierung implementieren.
Was ist jedoch, wenn der Benutzer beispielsweise die Seitengröße auf 100 festlegen möchte? Wie kann man das Problem lösen?
In diesem Fall können wir die Datenkomprimierung verwenden, um die Größe der Nutzlast zu reduzieren, die zwischen dem Server und dem Client übertragen wird. Zum Glück für .NET-Entwickler (und ich glaube, es ist auch für andere bekannte Frameworks relativ einfach) ist dies mit Hilfe von Middleware für die Antwortkomprimierung einfach zu implementieren.
Die Datenkomprimierung kann auf sehr einfache Weise erklärt werden, wenn wir uns vorstellen, dass wir ein großes Paket senden müssen. Wenn wir die Größe des Pakets reduzieren können, wird es schneller ankommen und wahrscheinlich weniger kosten. In dieser Analogie reduziert die Datenkomprimierung die „Größe“ der Informationen, die Ihre API an die Benutzer sendet, was zu einer schnelleren Datenbereitstellung führt.
Bei der Komprimierung werden CPU-Ressourcen verwendet. Das Festlegen der Komprimierungsstufe auf CompressionLevel.Fastest kann ein gutes Gleichgewicht zwischen der Komprimierungsgeschwindigkeit und der Reduzierung der Datengröße darstellen.
Als Teil des .NET Frameworks können wir die GZIP-Komprimierung verwenden, die direkt in Webanwendungen verwendet werden kann. Es gibt eine weitere Bibliothek, SharpCompress, die eine breite Palette von Komprimierungsformaten einschließlich GZIP bietet, mit denen Entwickler komprimierte Daten einfach verarbeiten können.
Fazit
Ich bin mir sicher, dass die meisten von Ihnen das bereits wissen, aber bei der Arbeit an Projekten ist mir aufgefallen, dass die oben genannten Optimierungsmechanismen oft nicht implementiert sind. Ich sehe sehr selten, dass die Paginierung implementiert ist – oder nur auf der Frontend-Seite, was sich direkt auf die Ladegeschwindigkeit auswirkt und zu einer schlechten Benutzererfahrung führt.
Oft ist es eine Folge der unpopulären Meinung „wir werden es später reparieren“, aber ich sehe selten, dass es wirklich später behoben wird.

Ich möchte auch erwähnen, dass es äußerst wichtig ist, immer ein Auge auf Watchdogs zu haben, und erstellen Sie mithilfe von Telemetriedaten oder Tools wie Application Insights oder SQL Server Profiler ein Profil für Ihre Anwendungen. Eine goldene Regel, die ich mir im Laufe der Jahre zu eigen gemacht habe, lautet: Was für eine Anwendung funktioniert, ist für eine andere möglicherweise nicht ideal.
Sobald Ihre Anwendung für die Produktion bereit ist, ist es, als würden Sie sie heiraten – erst wenn sie live ist, treten die Herausforderungen auf. Während Sie in einer romantischen Beziehung sind, haben Sie Probleme, aber sie können in ein Blütenblatt passen. Aber wenn Sie heiraten, seien Sie bereit und bereiten Sie den Kleiderschrank auf Probleme vor, da die Probleme viel größer sind.
Weiteres lesbares Thema: Die 5 wichtigsten Fähigkeiten, die Sie im Jahr 2025 erlernen sollten