Dieser Artikel folgt einer Präsentation, die bei den Human Talks im September 2022 gehalten wurde. Die Folien sind verfügbar ic.
Während meiner Mission bei Cinch 2021/2022 trat ich einem Team bei, das an öffentlichen APIs arbeitete, die hinter a API-Manager, Gravierte. Diese Plattform ermöglicht unter anderem die Kontrolle und Sicherung unserer APIs. Das „Ratenlimit“ besteht beispielsweise darin, die Anzahl der Aufrufe einer API in einem bestimmten Zeitintervall zu begrenzen.
Trotz der Implementierung dieses Schutzes war es uns wichtig, die Nutzungsgrenze unserer API und unserer Plattform abschätzen zu können. Mit der Ankunft neuer Kunden wird die Nutzung der API und damit die Belastungssteigerung progressiv sein.
Der Begriff „Charge Shot“ kann je nach Profil von Personen oder Unternehmen unterschiedlich definiert werden.
Für uns geht es beim Ausführen von Load Shots darum, in sehr kurzer Zeit eine große Anzahl von Aufrufen an unsere API zu simulieren, mit dem Ziel, „explodieren” unsere API.
Gatling: unser erster Belastungstest
Um diese Grenzen zu finden, wandten wir uns der Lösung zu Gatling. Warum nicht andere „schnellere“ Tools wie z arbeitenein Befehlszeilentool, das Entwicklungen nicht beeinflusst?
Bei RCA wird das Testökosystem mit der API aufgebaut Karateein automatisiertes Testtool, das darauf abzielt, einfach zu bedienen zu sein, egal ob Sie ein Entwickler oder eine weniger technisch versierte Person sind.
Mit der Sprache Gurke, können wir unsere Testszenarien schreiben. Zum Beispiel :
Feature: Guess the word # The first example has two steps Scenario: Maker starts a game When the Maker starts a game Then the Maker waits for a Breaker to join
Gatling kann diese Karate-Szenarien wiederverwenden, um Angriffsschüsse auszuführen. Die Integration in eine API ist sehr einfach. Holen Sie sich einfach die Abhängigkeit Karate-Gatling :
com.intuit.karate karate-gatling test
Als wir diese Workaround-Lasttests initiierten, war nur DSL Scala verfügbar. Inzwischen wurde eine Java-DSL erstellt.
class GatlingSimulation extends Simulation{ val test = scenario("tirs-charge").exec(karateFeature("classpath:scenarios/charge/tirs-charge.feature"))
Nach dem Erstellen eines Profils Maven Der folgende Befehl ist diesen Belastungstests gewidmet und ermöglicht die Ausführung unserer Klasse Gatling-Simulation: mvn clean test-compile gatling:test
Gatling generiert dann einen HTML-Bericht mit vollständigen Informationen über die Anzahl der gesendeten Anfragen, durchschnittliche Antwortzeiten, Anfragestatus, wie in den folgenden Berichten gezeigt:
Auf der ersten Grafik sehen wir schnell, dass die Indikatoren auf den ersten Blick richtig erscheinen. Die API beantwortete die 3.000 Anfragen in maximal 800 Millisekunden. Für eine API und nach unserer Erfahrung ein durchaus angemessener Wert.
Dieser Trend wird im Balkendiagramm bestätigt. Unsere API hat innerhalb von 200 ms geantwortet.
Die in den Diagrammen sichtbaren Reaktionszeitbereiche (800 ms, 1200 ms) sind von Gatling definierte Basiswerte.
Integration | Automatisierung in CI/CD
Nachdem das Gatling-Szenario geschrieben wurde, ist es durchaus möglich, es zu testen, indem Sie es auf Ihrer eigenen Workstation ausführen. Ein Load-Shot auf einer API, die auf einem eigenen Computer bereitgestellt wird, ist es auch. Aber was bringt es, diesen Test lokal oder von Ihrer Workstation aus durchzuführen? Jeder Schuss hängt von der Leistung und Kapazität Ihres Computers zu diesem Zeitpunkt ab. Wenn es unser Ziel ist, Grenzen für unsere API zu finden, führt dies nicht zu einer relevanten Bilanz.
Um interpretierbare Ergebnisse zu erhalten, haben wir unsere API auf einer Infrastruktur bereitgestellt „testen“, fast gleichbedeutend mit dem der Produktion. Es ist leicht unterdimensioniert.
Wie bereits erwähnt, bestand unser Ziel darin, uns ein Aufforderungslimit zu geben, damit unsere API akzeptable Antwortzeiten hat. Die Infrastruktur, auf der die Karate-Szenarien laufen, musste daher leistungsfähig genug sein, was bei unseren Computern nicht der Fall ist.
Was bringt es, Tools wie Maven zu installieren, um einen Charge Shot ausführen zu können?
Die relativ einfach zu bedienende Benutzeroberfläche von GitLab ermöglicht es jedem Profil, Pipelines schnell auszulösen. Bei RCA, dem Mechanismus, der die Pipelines betreibt, GitLab-Runnerist auf einer leistungsfähigen Infrastruktur installiert.
Wir haben einen neuen Arbeitsplatz geschaffen“🧯Schüsse beim Testen laden 🔥“ in unserer bestehenden GitLab-Pipeline, um es zu ermöglichen, einen Ladevorgang auf unserer API auszuführen, die in der Produktions-ISO-Umgebung bereitgestellt wird.
Die aufgetretenen Probleme (und Lösungen)
Infrastruktur als Code
Der Aufruf unserer API erfolgt nach dem Abrufen eines Authentifizierungstokens über Gravitee. Wir hatten ein „Ratenlimit“ von 1000 Anrufen für einen Zeitraum von 10 Minuten festgelegt. Während unseres Ladevorgangs führten wir mehrere Zehntausend Anrufe in 1 Minute durch. Das „Ratenlimit“ ist logischerweise erreicht!
Trotz einer Modifikation der Testinfrastruktur zur Deaktivierung dieser „Ratenbegrenzung“ ist ein weiterer Knackpunkt aufgetreten.
Single anrufen
In unserem Karate-Szenario verursacht 1 Aufruf an die API 1 Aufruf an Gravitee. Für mehrere zehntausend Aufrufe haben wir also die gleiche Menge an Tokens erstellt. Unser Ladungsschuss soll jedoch nicht die Robustheit von Gravity testen. Zumal das Team, das diese Infrastruktur aufgebaut hat, für deren Leistungsfähigkeit gesorgt hatte.
Und aus anderer Sicht macht es keinen Sinn, so viele Token zu generieren, also könnten wir genauso gut nur einen für unsere Tests erstellen.
Dazu stellt die Karate-API eine Methode bereit AnrufSingle eine Ressource nur einmal aufzurufen, in unserem Fall die Generierung des Tokens.
var result = karate.callSingle('classpath:scenarios/api/authentification.feature', config);
Das Ergebnis der Ausführung dieses Befehls kann in der folgenden generierten Tabelle auf der Ebene der rot eingekreisten Zeile überprüft werden: 1 einzelne Ausführung auf der Ressource POST /Bearer/Token wurde produziert.
Dies hat zur Folge, dass unser Charge Shot während der Gültigkeit des Tokens ausgeführt werden muss, unter Strafe der Generierung einer großen Anzahl von Fehlern 401 nicht Autorisiert.
Ergebnisanalyse
Um ein Limit für unsere API zu bestimmen, haben wir mehrere Laderunden durchgeführt. Beginnend mit einigen hundert Anrufen pro Minute haben wir die Anzahl der Anrufe schrittweise erhöht, die Ausführungszeit verkürzt, bis wir schlechtere Reaktionszeiten für die Lieferung an unsere Kunden hatten.
In den folgenden von Gatling generierten Diagrammen sind zwei Informationen verfügbar: die Anzahl der Anfragen und die Anzahl der Benutzer zu einem Zeitpunkt t.
Diese Daten sind stabil und zeigen, dass während des Brennens kein Klebepunkt auftritt. Die Anzahl der Anfragen ist stabil.
Neben den Diagrammen bietet Gatling einen textuellen Report mit der Anzahl der Anfragen während des Schusses, der maximalen Antwortzeit sowie Statistiken zur Verteilung der Antwortzeiten.
Ein wichtiger repräsentativer Datenwert für den Zustand unserer API ist der CPU-Verbrauch. Diese Informationen sind in den bei RCA vorhandenen Grafana-Dashboards verfügbar, die es uns ermöglichen, unsere Interpretation der Ergebnisse von Gatling zu validieren.
Wir sind gekommen, um ein Limit für unsere API zu identifizieren. Eine Aufnahme, die 50.000 Benutzer über 30 Sekunden simuliert, liefert uns akzeptable Reaktionszeiten, d. h. unter 800 ms.
Die von RCA erstellte kollaborative Plattform hat ein Produktionsvolumen von 12.000 bis 16.000 Benutzern pro Stunde. In dem Wissen, dass die Umgebung im Vergleich zur Produktion außerdem unterdimensioniert ist, werden diese 50.000 Benutzer in 30 Sekunden in der Lage sein, unsere API weitgehend anzufordern.
Die Beiträge dieses Experiments
Die Integration von charge shots in unser Team war eine Entdeckung. Nachdem wir uns mit der Karate-API und der Gatling-Erweiterung auseinandergesetzt hatten, konnten wir schnell unsere ersten Ergebnisse verwerten und uns eine Größenordnung über die Aufrufkapazität unserer API geben.
Glücklicherweise wurden diese Tests durchgeführt, sie ermöglichten es uns, ein Leistungsproblem zu erkennen und zu beheben. Dies ist beruhigend für die weitere Entwicklung und schützt uns vor ähnlichen Problemen.
Lasttests im gesamten Team zu integrieren, ist eine gute Sache. Mit der Sensibilisierung und Automatisierung von Load Shots in GitLab CI kann jedes Personenprofil Load Shots ausführen, das Diagramm abrufen und eine erste Interpretation davon vornehmen.
Sylvain Nagel (Cinch) / Jean-Philippe Baconnais (Zenika)
Finden Sie diesen Artikel auf der Sylvains Medium-Konto und innerhalb weniger Tage auf der RCA-Blog.