Maison  >  Article  >  Java  >  Application Spring Boot sur AWS Lambda - Partie Mesurer les démarrages à froid et à chaud avec Spring Cloud Function

Application Spring Boot sur AWS Lambda - Partie Mesurer les démarrages à froid et à chaud avec Spring Cloud Function

WBOY
WBOYoriginal
2024-08-12 22:38:321070parcourir

Spring Boot pplication on AWS Lambda - Part Measuring cold and warm starts with Spring Cloud Function

Introduction

Dans la partie 8, nous présentons le concept derrière la fonction Spring Cloud et dans la partie 9, nous avons démontré comment développer AWS Lambda avec Spring Cloud Function à l'aide de Java 21 et Spring Boot 3.2. Dans cet article de la série, nous mesurerons l'heure de démarrage à froid et à chaud, notamment en activant SnapStart sur la fonction Lambda, mais également en appliquant diverses techniques d'amorçage telles que l'amorçage de l'invocation DynamoDB et l'amorçage (proxy) de l'ensemble de la requête API Gateway sans passer par le réseau. . Nous utiliserons l'exemple d'application Spring Boot 3.2 pour nos mesures, et pour toutes les fonctions Lambda, nous utiliserons JAVA_TOOL_OPTIONS : "-XX:+TieredCompilation -XX:TieredStopAtLevel=1" et leur attribuerons 1 024 Mo de mémoire Lambda.

Mesurer les démarrages à froid et les temps chauds avec Spring Cloud Function et utiliser Java 21 et Spring Boot 3.2

Commençons par expliquer comment activer AWS SnapStart sur la fonction Lambda, car elle (avec l'amorçage en haut) offre le plus grand potentiel d'optimisation des performances Lambda (en particulier les temps de démarrage à froid). Ce n'est qu'une question de configuration :

SnapStart:
  ApplyOn: PublishedVersions 

appliqué dans les propriétés de la fonction Lambda ou dans la section des fonctions globales du modèle SAM. J'aimerais approfondir la façon d'utiliser diverses techniques d'amorçage en plus de SnpaStart pour notre cas d'utilisation. J'ai expliqué les idées derrière l'amorçage dans mon article AWS Lambda SnapStart - Mesurer l'amorçage, la latence de bout en bout et le temps de déploiement

1) Le code pour l'amorçage de la requête DynamoDB peut être trouvé ici.

Cette classe implémente en outre l'interface import org.crac.Resource du projet CraC.

Avec cette invocation

Core.getGlobalContext().register(this);

La classe GetProductByIdWithDynamoDBRequestPrimingHandler s'enregistre en tant que ressource CRaC.

Nous amorçons également l'invocation DynamoDB en implémentant la méthode beforeCheckpoint à partir de l'API CRaC.

      @Override
      public void beforeCheckpoint(org.crac.Context<? extends Resource> context) throws Exception {
             productDao.getProduct("0");
      }

que nous invoquerons pendant la phase de déploiement de la fonction Lambda et avant la prise de l'instantané de la microVM Firecracker.

2) Le code pour l'amorçage de l'ensemble de la requête API Gateway peut être trouvé ici.

Cette classe implémente également l'interface import org.crac.Resource comme dans l'exemple ci-dessus.
Nous réutiliserons la technique laide, que j'ai décrite dans mon article AWS Lambda SnapStart - Partie 6 Amorçage de l'invocation de requête pour les frameworks Java 11 et Micronaut, Quarkus et Spring Boot. Je ne recommande pas d'utiliser cette technique en production, mais elle démontre les potentiels supplémentaires de réduction du démarrage à froid en utilisant l'amorçage de l'ensemble de la requête API Gateway en préchargeant le mappage entre les modèles Spring Boot et Spring Cloud Function et le modèle Lambda exécutant également DynamoDB. amorçage d'invocation.

La construction de la requête API Gateway du /products/{id} avec l'identifiant est égal à 0. La requête API Gateway JSON ressemble à ceci :

      private static String getAPIGatewayRequestMultiLine () {
             return  """
                        {
                      "resource": "/products/{id}",
                      "path":  "/products/0",
                      "httpMethod": "GET",
                      "pathParameters": {
                            "id": "0" 
                        },
                       "requestContext": {
                          "identity": {
                        "apiKey": "blabla"
                      }
                      }
                    }
           """;
      }

Le beforeCheckpoint lorsqu'il amorce (proxy) l'intégralité de la requête API Gateway sans passer par le réseau à l'aide de la classe Spring Cloud Function FunctionInvoker qui invoque sa méthode handleRequest en transmettant le flux d'entrée de l'API Requête Gateway JSON construite ci-dessus comme ceci :

@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());
}

Les résultats de l'expérience ci-dessous étaient basés sur la reproduction de plus de 100 démarrages à froid et environ 100 000 démarrages à chaud avec la fonction Lambda avec un réglage de mémoire de 1024 Mo pour une durée d'1 heure. Pour cela, j'ai utilisé l'outil de test de charge, mais vous pouvez utiliser l'outil de votre choix, comme Serverless-artillerie ou Postman.

J'ai mené toutes ces expériences avec 4 scénarios différents :

1) Aucun SnapStart activé

Dans template.yaml, utilisez la configuration suivante :

    Handler: org.springframework.cloud.function.adapter.aws.FunctionInvoker::handleRequest    
      #SnapStart:
         #ApplyOn: PublishedVersions      

et nous devons invoquer la fonction Lambda avec le nom GetProductByIdWithSpringBoot32SCF qui est mappé à la classe Java GetProductByIdHandler Lambda Handler.

2) SnapStart activé mais aucun amorçage appliqué

Dans template.yaml, utilisez la configuration suivante :

    Handler: org.springframework.cloud.function.adapter.aws.FunctionInvoker::handleRequest 
    SnapStart:
      ApplyOn: PublishedVersions 

et nous devons invoquer la même fonction Lambda avec le nom GetProductByIdWithSpringBoot32SCF qui est mappée à la classe Java GetProductByIdHandler Lambda Handler.
3) SnapStart activé avec l'amorçage des invocations DynamoDB

Dans template.yaml, utilisez la configuration suivante :

    Handler: org.springframework.cloud.function.adapter.aws.FunctionInvoker::handleRequest    
    SnapStart:
      ApplyOn: PublishedVersions      

et nous devons invoquer la fonction Lambda avec le nom GetProductByIdWithSpringBoot32SCFAndDynamoDBRequestPriming qui est mappée à la classe Java GetProductByIdWithDynamoDBRequestPrimingHandler Lambda Handler.

4) SnapStart activé avec l'amorçage/le proxy d'invocation de demande API Gateway

Dans template.yaml, utilisez la configuration suivante :

    Handler: org.springframework.cloud.function.adapter.aws.FunctionInvoker::handleRequest
    SnapStart:
      ApplyOn: PublishedVersions      

and we need to invoke Lambda function with name
GetProductByIdWithSpringBoot32SCFAndWebRequestPriming which is mapped to the GetProductByIdWithWebRequestPrimingHandler Lambda Handler Java class.

Abbreviation c is for the cold start and w is for the warm start.

Cold (c) and warm (w) start time in ms:

Scenario Number 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
No SnapStart enabled 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 enabled but no priming applied 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 enabled with DynamoDB invocation priming 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 enabled with API Gateway request invocation 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

Conclusion

By enabling SnapStart on the Lambda function alone, it reduces the cold start time of the Lambda function significantly. By additionally using DynamoDB invocation priming we are be able to achieve cold starts only slightly higher than cold starts described in my article AWS SnapStart -Measuring cold and warm starts with Java 21 using different memory settings where we measured cold and warm starts for the pure Lambda function without the usage of any frameworks including 1024MB memory setting like in our scenario.

Comparing the cold and warm start times we measured with AWS Serverless Java Container in the article Measuring cold and warm starts with AWS Serverless Java Container and Measuring cold and warm starts with AWS Lambda Web Adapter we observe that Spring Cloud Function offers higher cold start times than AWS Lambda Web Adapter but quite comparable cold start times to AWS Serverless Java Container (results vary slightly depending on the percentiles). In terms of warm start/execution times all 3 approaches have quite comparable results when especially looking into the percentiles below 99.9.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn