Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Das Einfügen aller Daten einer Anwendung in einen einzelnen Datenspeicher kann die Leistung schwächen, entweder weil sie zu Ressourcenkonflikten führt oder weil der Datenspeicher für einige daten nicht gut geeignet ist.
Kontext und Problem
In der Vergangenheit verwendeten Anwendungen einen einzelnen Datenspeicher, unabhängig von den verschiedenen Datentypen, die die Anwendung möglicherweise speichern muss. Organisationen haben diese Methode verwendet, um das Anwendungsdesign zu vereinfachen oder den vorhandenen Fähigkeiten des Entwicklungsteams zu entsprechen.
Moderne cloudbasierte Systeme verfügen häufig über zusätzliche funktionale und nicht funktionale Anforderungen. Diese Systeme müssen viele heterogene Datentypen speichern, z. B. Dokumente, Bilder, zwischengespeicherte Daten, in die Warteschlange eingereihte Nachrichten, Anwendungsprotokolle und Telemetrie. Nach dem herkömmlichen Ansatz und dem Einfügen aller dieser Informationen in denselben Datenspeicher kann die Leistung aus zwei Hauptgründen geschwächt werden:
- Das Speichern und Abrufen großer Mengen von nicht verknüpften Daten im selben Datenspeicher kann zu einem Streit führen, was zu langsamen Reaktionszeiten und Verbindungsfehlern führt.
- Unabhängig davon, welcher Datenspeicher ausgewählt wird, ist er möglicherweise nicht für alle Datentypen am besten geeignet. Oder es ist möglicherweise nicht für die Vorgänge optimiert, die die Anwendung ausführt.
Das folgende Beispiel zeigt einen ASP.NET Web-API-Controller, der einer Datenbank einen neuen Datensatz hinzufügt und das Ergebnis auch in einem Protokoll erfasst. Das Protokoll wird in derselben Datenbank wie die Geschäftsdaten gespeichert.
public class MonoController : ApiController
{
private static readonly string ProductionDb = ...;
public async Task<IHttpActionResult> PostAsync([FromBody]string value)
{
await DataAccess.InsertPurchaseOrderHeaderAsync(ProductionDb);
await DataAccess.LogAsync(ProductionDb, LogTableName);
return Ok();
}
}
Die Häufigkeit, mit der Protokolldatensätze generiert werden, kann sich auf die Leistung der Geschäftsvorgänge auswirken. Und wenn eine andere Komponente, z. B. eine Anwendungsprozessüberwachung, regelmäßig die Protokolldaten liest und verarbeitet, kann sich dies auch auf die Geschäftsvorgänge auswirken.
Lösung
Trennen Sie Daten entsprechend ihrer Verwendung. Wählen Sie für jeden Datensatz einen Datenspeicher aus, der am besten der Verwendung dieses Datasets entspricht. Im vorherigen Beispiel sollte die Anwendung sich in einem separaten Speicher von der Datenbank anmelden, in dem Geschäftsdaten gespeichert sind:
public class PolyController : ApiController
{
private static readonly string ProductionDb = ...;
private static readonly string LogDb = ...;
public async Task<IHttpActionResult> PostAsync([FromBody]string value)
{
await DataAccess.InsertPurchaseOrderHeaderAsync(ProductionDb);
// Log to a different data store.
await DataAccess.LogAsync(LogDb, LogTableName);
return Ok();
}
}
Probleme und Überlegungen
Trennen Sie Daten basierend auf der Verwendung und dem Zugriff darauf. Speichern Sie beispielsweise keine Protokollinformationen und Geschäftsdaten im selben Datenspeicher. Diese Arten von Daten weisen unterschiedliche Anforderungen und Zugriffsmuster auf. Protokolldaten sind inhärent sequenziell, während Geschäftsdaten eher zufälligen Zugriff erfordern und häufig relational sind.
Berücksichtigen Sie das Datenzugriffsmuster für jeden Datentyp. Speichern Sie beispielsweise formatierte Berichte und Dokumente in einer Dokumentdatenbank wie Azure Cosmos DB. Verwenden Sie Azure Cache für Redis , um temporäre Daten zwischenzuspeichern.
Skalieren Sie die Datenbank, wenn Sie diese Anleitung befolgen, aber dennoch die Grenzen der Datenbank erreichen. Erwägen Sie auch die horizontale Skalierung und Partitionierung der Last auf Datenbankservern. Die Partitionierung kann jedoch eine Neugestaltung der Anwendung erfordern. Weitere Informationen finden Sie unter "Datenpartitionierung".
Erkennen des Problems
Das System kann erheblich langsamer werden und letztendlich ausfallen, wenn dem System Ressourcen wie z. B. Datenbankverbindungen ausgehen.
Sie können die folgenden Schritte ausführen, um die Ursache zu ermitteln:
Instrumentieren Sie das System, um die wichtigsten Leistungsstatistiken aufzuzeichnen. Erfassen Sie Zeitinformationen für jede Operation. Und erfassen Sie die Punkte, an denen die Anwendung Daten liest und schreibt.
Überwachen Sie das System einige Tage in einer Produktionsumgebung, um eine echte Ansicht der Verwendung des Systems zu erhalten. Wenn Sie diesen Vorgang nicht ausführen können, führen Sie Skriptlasttests mit einem realistischen Volumen virtueller Benutzer aus, die eine typische Reihe von Vorgängen ausführen.
Verwenden Sie die Telemetriedaten, um Zeiträume mit schlechter Leistung zu identifizieren.
Identifizieren Sie, auf welche Datenspeicher während dieser Zeiträume zugegriffen wurde.
Identifizieren Sie Speicherressourcen, bei denen es möglicherweise zu Engpässen kommen könnte.
Beispieldiagnose
In den folgenden Abschnitten werden diese Schritte auf die zuvor beschriebene Beispielanwendung angewendet.
Instrumentieren und Überwachen des Systems
Das folgende Diagramm zeigt die Ergebnisse des Ladentests der zuvor beschriebenen Beispielanwendung. Der Test verwendet eine Schrittlast von bis zu 1.000 gleichzeitigen Benutzern.
Mit steigender Last auf 700 Benutzer erhöht sich auch der Durchsatz. Aber zu diesem Zeitpunkt stabilisiert sich der Durchsatz, und das System scheint bei seiner maximalen Kapazität zu laufen. Die durchschnittliche Antwort steigt schrittweise mit der Benutzerauslastung, was zeigt, dass das System nicht mit der Nachfrage schritthalten kann.
Identifizieren von Zeiträumen mit schlechter Leistung
Wenn Sie das Produktionssystem überwachen, bemerken Sie möglicherweise Muster. Beispielsweise können die Reaktionszeiten zur gleichen Zeit jeden Tag erheblich abfallen. Eine regelmäßige Arbeitslast oder ein geplanter Stapelauftrag kann zu dieser Fluktuation führen. Oder das System kann zu bestimmten Zeiten mehr Benutzer haben. Sie sollten sich auf die Telemetriedaten für diese Ereignisse konzentrieren.
Suchen Sie nach Korrelationen zwischen erhöhten Reaktionszeiten und erhöhter Datenbankaktivität oder Eingabe/Ausgabe (E/A) bei freigegebenen Ressourcen. Wenn Es Korrelationen gibt, bedeutet dies, dass die Datenbank möglicherweise ein Engpass ist.
Ermitteln, auf welche Datenspeicher während dieser Zeiträume zugegriffen wird
Das nächste Diagramm zeigt die Verwendung von Datenbankdurchsatzeinheiten (DTUs) während des Auslastungstests. Eine DTU ist ein Maß an verfügbarer Kapazität. Es ist eine Kombination aus CPU-Auslastung, Speicherzuweisung und E/A-Rate. Die Nutzung von DTUs erreicht schnell 100%. Im vorherigen Diagramm wurde der Durchsatz an diesem Punkt hochgespitzt. Die Datenbankauslastung bleibt hoch, bis der Test abgeschlossen ist. Es gibt einen leichten Rückgang am Ende, der sich aus Drosselung, Wettbewerb für Datenbankverbindungen oder anderen Faktoren ergeben kann.
Überprüfen Sie die Telemetrie der Datenspeicher
Instrumentieren Sie die Datenspeicher, um die Details der Aktivität auf niedriger Ebene zu erfassen. In der Beispielanwendung zeigen die Datenzugriffsstatistiken ein hohes Volumen an Einfügevorgängen, die sowohl für die PurchaseOrderHeader
Tabelle als auch für die MonoLog
Tabelle ausgeführt werden.
Ressourcenengpass identifizieren
An diesem Punkt können Sie den Quellcode überprüfen und sich auf die Punkte konzentrieren, an denen die Anwendung auf die behaupteten Ressourcen zugreift. Suchen Sie nach Situationen wie:
- Daten, die logisch getrennt werden, werden in denselben Speicher geschrieben. Daten wie Protokolle, Berichte und Nachrichten in der Warteschlange sollten nicht in derselben Datenbank wie Geschäftsinformationen gespeichert werden.
- Ein Konflikt zwischen der Auswahl des Datenspeichers und dem Datentyp, z. B. großen Blobs oder XML-Dokumenten in einer relationalen Datenbank.
- Daten mit unterschiedlichen Verwendungsmustern, die denselben Speicher gemeinsam nutzen. Ein Beispiel beinhaltet Daten mit hoher Schreib- und niedriger Lesefrequenz, die zusammen mit Daten mit niedriger Schreib- und hoher Lesefrequenz gespeichert werden.
Implementieren der Lösung und Überprüfen des Ergebnisses
In diesem Beispiel wird die Anwendung aktualisiert, um Protokolle in einen separaten Datenspeicher zu schreiben. Das folgende Diagramm zeigt die Auslastungstestergebnisse.
Das Muster des Durchsatzes ähnelt dem früheren Diagramm, aber der Punkt, an dem die Leistung ihren Höhepunkt erreicht, liegt ungefähr 500 Anfragen pro Sekunde höher. Die durchschnittliche Reaktionszeit ist geringfügig niedriger. Diese Statistiken erzählen jedoch nicht die ganze Geschichte. Die Telemetrie der Geschäftsdatenbank zeigt, dass die Spitzen der DTU-Auslastung bei rund 75%liegen, statt bei 100%.
Ebenso erreicht die maximale DTU-Auslastung der Protokolldatenbank nur etwa 70%. Die Datenbanken sind nicht mehr der begrenzende Faktor bei der Leistung des Systems.