"Si un ouvrier veut bien faire son travail, il doit d'abord affûter ses outils." - Confucius, "Les Entretiens de Confucius. Lu Linggong"
Page de garde > La programmation > 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

Publié le 2024-08-19
Parcourir:906

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 améliorons é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 appellerons 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 (proxies) l'ensemble 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 d'environ 100 000 démarrages à chaud avec la fonction Lambda avec un réglage de mémoire de 1 024 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é à la classe Java GetProductByIdWithDynamoDBRequestPrimingHandler Lambda Handler.

4) SnapStart activé avec l'amorçage/le proxy d'appel de requête API Gateway

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
GetProductByIdWithSpringBoot32SCFAndWebRequestPriming qui est mappé à la classe Java GetProductByIdWithWebRequestPrimingHandler Lambda Handler.

Abréviation c désigne le démarrage à froid et w désigne le démarrage à chaud.

Heure de démarrage à froid (c) et à chaud (w) en ms :

Numéro du scénario 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
Aucun SnapStart activé 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 activé mais aucun amorçage appliqué 2006.60 2065.61 2180.17 2604,69 2662,60 2663,54 7.45 8h40 9,92 23.09 1354,50 1496,46
SnapStart activé avec l'amorçage des appels DynamoDB 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 activé avec l'amorçage des appels de requêtes API Gateway 855,45 953.91 1107.10 1339,97 1354,78 1355.21 8h00 9,53 12.09 26.31 163,26 547,28

Conclusion

En activant SnapStart uniquement sur la fonction Lambda, cela réduit considérablement le temps de démarrage à froid de la fonction Lambda. En utilisant également l'amorçage des invocations DynamoDB, nous sommes en mesure d'obtenir des démarrages à froid légèrement supérieurs aux démarrages à froid décrits dans mon article AWS SnapStart - Mesure des démarrages à froid et à chaud avec Java 21 en utilisant différents paramètres de mémoire où nous avons mesuré les démarrages à froid et à chaud pour le Lambda pur. fonctionner sans utiliser de framework, y compris un paramètre de mémoire de 1 024 Mo, comme dans notre scénario.

En comparant les temps de démarrage à froid et à chaud que nous avons mesurés avec AWS Serverless Java Container dans l'article Mesurer les démarrages à froid et à chaud avec AWS Serverless Java Container et Mesurer les démarrages à froid et à chaud avec AWS Lambda Web Adapter, nous observons que la fonction Spring Cloud offre des temps de démarrage à froid plus élevés. des temps de démarrage supérieurs à ceux d'AWS Lambda Web Adaptor mais des temps de démarrage à froid assez comparables à ceux d'AWS Serverless Java Container (les résultats varient légèrement en fonction des percentiles). En termes de temps de démarrage/d'exécution à chaud, les 3 approches ont des résultats assez comparables, notamment en examinant les centiles inférieurs à 99,9.

Déclaration de sortie Cet article est reproduit à l'adresse : https://dev.to/aws-builders/spring-boot-3-application-on-aws-lambda-part-10-measuring-cold-and-warm-starts-with-spring- cloud- function-2b1i?1En cas d'infraction, veuillez contacter [email protected] pour la supprimer
Dernier tutoriel Plus>

Clause de non-responsabilité: Toutes les ressources fournies proviennent en partie d'Internet. En cas de violation de vos droits d'auteur ou d'autres droits et intérêts, veuillez expliquer les raisons détaillées et fournir une preuve du droit d'auteur ou des droits et intérêts, puis l'envoyer à l'adresse e-mail : [email protected]. Nous nous en occuperons pour vous dans les plus brefs délais.

Copyright© 2022 湘ICP备2022001581号-3