In Teil 8 stellen wir das Konzept hinter der Spring Cloud-Funktion vor und in Teil 9 zeigen wir, wie man AWS Lambda mit Spring Cloud Function unter Verwendung von Java 21 und Spring Boot 3.2 entwickelt. In diesem Artikel der Serie messen wir die Kalt- und Warmstartzeit, einschließlich der Aktivierung von SnapStart für die Lambda-Funktion, aber auch der Anwendung verschiedener Vorbereitungstechniken wie der Vorbereitung des DynamoDB-Aufrufs und der Vorbereitung (Proxy) der gesamten API-Gateway-Anfrage, ohne über das Netzwerk zu gehen . Wir verwenden die Beispielanwendung Spring Boot 3.2 für unsere Messungen und verwenden für alle Lambda-Funktionen JAVA_TOOL_OPTIONS: „-XX: TieredCompilation -XX:TieredStopAtLevel=1“ und geben ihnen Lambda 1024 MB Speicher.
Beginnen wir mit der Erläuterung, wie man AWS SnapStart für die Lambda-Funktion aktiviert, da diese (mit der Grundierung oben) das größte Optimierungspotenzial für die Lambda-Leistung (insbesondere Kaltstartzeiten) bietet. Es ist nur eine Frage der Konfiguration:
SnapStart: ApplyOn: PublishedVersions
wird in den Lambda-Funktionseigenschaften oder im globalen Funktionsabschnitt der SAM-Vorlage angewendet. Für unseren Anwendungsfall möchte ich näher auf die Verwendung verschiedener Priming-Techniken zusätzlich zu SnpaStart eingehen. Die Ideen hinter dem Priming habe ich in meinem Artikel AWS Lambda SnapStart – Messung von Priming, End-to-End-Latenz und Bereitstellungszeit
erläutert.1) Den Code zum Priming der DynamoDB-Anfrage finden Sie hier.
Diese Klasse implementiert zusätzlich die Schnittstelle import org.crac.Resource des CraC-Projekts.
Mit diesem Aufruf
Core.getGlobalContext().register(this);
GetProductByIdWithDynamoDBRequestPrimingHandler-Klasse registriert sich selbst als CRaC-Ressource.
Wir bereiten den DynamoDB-Aufruf zusätzlich vor, indem wir die Methode beforeCheckpoint aus der CRaC-API implementieren.
@Override public void beforeCheckpoint(org.crac.Context extends Resource> context) throws Exception { productDao.getProduct("0"); }
die wir während der Bereitstellungsphase der Lambda-Funktion aufrufen werden und bevor der Firecracker-MicroVM-Snapshot erstellt wird.
2) Den Code zum Priming der gesamten API-Gateway-Anfrage finden Sie hier.
Diese Klasse implementiert außerdem zusätzlich die Schnittstelle import org.crac.Resource wie im obigen Beispiel.
Wir werden die hässliche Technik wiederverwenden, die ich in meinem Artikel AWS Lambda SnapStart – Teil 6 Priming the request invocation for Java 11 and Micronaut, Quarkus and Spring Boot Frameworks beschrieben habe. Ich empfehle nicht, diese Technik in der Produktion zu verwenden, aber sie zeigt die weiteren Möglichkeiten zur Reduzierung des Kaltstarts durch Priming der gesamten API-Gateway-Anfrage durch Vorladen der Zuordnung zwischen Spring Boot- und Spring Cloud-Funktionsmodellen und Lambda-Modell, das auch DynamoDB ausführt Aufruf-Priming.
Die API-Gateway-Anfragekonstruktion der /products/{id} mit der ID gleich 0 sieht folgendermaßen aus:
private static String getAPIGatewayRequestMultiLine () { return """ { "resource": "/products/{id}", "path": "/products/0", "httpMethod": "GET", "pathParameters": { "id": "0" }, "requestContext": { "identity": { "apiKey": "blabla" } } } """; }
Der beforeCheckpoint, wenn die gesamte API-Gateway-Anfrage vorbereitet (Proxys) wird, ohne das Netzwerk zu durchlaufen, mithilfe der Spring Cloud Function-Klasse FunctionInvoker, die ihre handleRequest-Methode aufruft, indem sie den Eingabestrom der API übergibt Die oben beschriebene Gateway-JSON-Anfrage sieht wie folgt aus:
@Override public void beforeCheckpoint(org.crac.Context extends Resource> context) throws Exception { new FunctionInvoker().handleRequest( new ByteArrayInputStream(getAPIGatewayRequestMultiLine(). getBytes(StandardCharsets.UTF_8)), new ByteArrayOutputStream(), new MockLambdaContext()); }
Die Ergebnisse des folgenden Experiments basierten auf der Reproduktion von mehr als 100 Kalt- und etwa 100.000 Warmstarts mit Lambda-Funktion mit 1024 MB Speichereinstellung für die Dauer von 1 Stunde. Dafür habe ich das Lasttest-Tool verwendet, aber Sie können jedes beliebige Tool verwenden, z. B. Serverless-Artillery oder Postman.
Ich habe alle diese Experimente mit 4 verschiedenen Szenarien durchgeführt:
1) Kein SnapStart aktiviert
Verwenden Sie in template.yaml die folgende Konfiguration:
Handler: org.springframework.cloud.function.adapter.aws.FunctionInvoker::handleRequest #SnapStart: #ApplyOn: PublishedVersions
und wir müssen die Lambda-Funktion mit dem Namen GetProductByIdWithSpringBoot32SCF aufrufen, die der Java-Klasse GetProductByIdHandler Lambda Handler zugeordnet ist.
2) SnapStart aktiviert, aber keine Grundierung angewendet
Verwenden Sie in template.yaml die folgende Konfiguration:
Handler: org.springframework.cloud.function.adapter.aws.FunctionInvoker::handleRequest SnapStart: ApplyOn: PublishedVersions
und wir müssen dieselbe Lambda-Funktion mit dem Namen GetProductByIdWithSpringBoot32SCF aufrufen, die der Java-Klasse GetProductByIdHandler Lambda Handler zugeordnet ist.
3) SnapStart aktiviert mit DynamoDB-Aufrufpriming
Verwenden Sie in template.yaml die folgende Konfiguration:
Handler: org.springframework.cloud.function.adapter.aws.FunctionInvoker::handleRequest SnapStart: ApplyOn: PublishedVersions
und wir müssen die Lambda-Funktion mit dem Namen GetProductByIdWithSpringBoot32SCFAndDynamoDBRequestPriming aufrufen, die der Java-Klasse GetProductByIdWithDynamoDBRequestPrimingHandler Lambda Handler zugeordnet ist.
4) SnapStart aktiviert mit API Gateway-Anforderungsaufruf-Priming/Proxying
Verwenden Sie in template.yaml die folgende Konfiguration:
Handler: org.springframework.cloud.function.adapter.aws.FunctionInvoker::handleRequest SnapStart: ApplyOn: PublishedVersions
und wir müssen die Lambda-Funktion mit dem Namen aufrufen
GetProductByIdWithSpringBoot32SCFAndWebRequestPriming, das der Java-Klasse GetProductByIdWithWebRequestPrimingHandler Lambda Handler zugeordnet ist.
Abkürzung c steht für Kaltstart und w steht für Warmstart.
Kalte (c) und warme (w) Startzeit in ms:
Szenarionummer | c p50 | c p75 | c p90 | c p99 | c p99.9 | c max | w p50 | w p75 | w p90 | w p99 | w p99.9 | w max |
---|---|---|---|---|---|---|---|---|---|---|---|---|
Kein SnapStart aktiviert | 4768,34 | 4850.11 | 4967,86 | 5248,61 | 5811,92 | 5813,31 | 7.16 | 8.13 | 9,53 | 21,75 | 62,00 | 1367,52 |
SnapStart aktiviert, aber keine Vorbereitung angewendet | 2006.60 | 2065,61 | 2180,17 | 2604,69 | 2662,60 | 2663,54 | 7,45 | 8,40 | 9,92 | 23.09 | 1354,50 | 1496,46 |
SnapStart aktiviert mit DynamoDB-Aufrufvorbereitung | 1181,40 | 1263,23 | 1384,90 | 1533,54 | 1661,20 | 1662,17 | 7,57 | 8,73 | 10,83 | 23,83 | 492,37 | 646,18 |
SnapStart aktiviert mit API Gateway-Anforderungsaufruf-Priming | 855,45 | 953,91 | 1107.10 | 1339,97 | 1354,78 | 1355,21 | 8.00 | 9,53 | 12.09 | 26,31 | 163,26 | 547,28 |
Durch die Aktivierung von SnapStart allein für die Lambda-Funktion wird die Kaltstartzeit der Lambda-Funktion erheblich verkürzt. Durch die zusätzliche Verwendung des DynamoDB-Aufrufprimings können wir Kaltstarts erzielen, die nur geringfügig höher sind als die Kaltstarts, die in meinem Artikel „AWS SnapStart – Messen von Kalt- und Warmstarts mit Java 21 unter Verwendung unterschiedlicher Speichereinstellungen“ beschrieben werden, in dem wir Kalt- und Warmstarts für das reine Lambda gemessen haben funktioniert ohne die Verwendung von Frameworks einschließlich der 1024-MB-Speichereinstellung wie in unserem Szenario.
Beim Vergleich der Kalt- und Warmstartzeiten, die wir mit AWS Serverless Java Container im Artikel Messen von Kalt- und Warmstarts mit AWS Serverless Java Container und Messen von Kalt- und Warmstarts mit AWS Lambda Web Adapter gemessen haben, stellen wir fest, dass die Spring Cloud-Funktion höhere Kaltstarts bietet Startzeiten als AWS Lambda Web Adaptor, aber durchaus vergleichbare Kaltstartzeiten wie AWS Serverless Java Container (Ergebnisse variieren leicht je nach Perzentil). In Bezug auf die Warmstart-/Ausführungszeiten erzielen alle drei Ansätze durchaus vergleichbare Ergebnisse, insbesondere wenn man sich die Perzentile unter 99,9 ansieht.
Haftungsausschluss: Alle bereitgestellten Ressourcen stammen teilweise aus dem Internet. Wenn eine Verletzung Ihres Urheberrechts oder anderer Rechte und Interessen vorliegt, erläutern Sie bitte die detaillierten Gründe und legen Sie einen Nachweis des Urheberrechts oder Ihrer Rechte und Interessen vor und senden Sie ihn dann an die E-Mail-Adresse: [email protected] Wir werden die Angelegenheit so schnell wie möglich für Sie erledigen.
Copyright© 2022 湘ICP备2022001581号-3