Na parte 8 apresentamos o conceito por trás da função Spring Cloud e na parte 9 demonstramos como desenvolver AWS Lambda com Spring Cloud Function usando Java 21 e Spring Boot 3.2. Neste artigo da série, mediremos o tempo de inicialização a frio e a quente, incluindo a ativação do SnapStart na função Lambda, mas também a aplicação de várias técnicas de preparação, como preparação da invocação do DynamoDB e preparação (proxy) de toda a solicitação do API Gateway sem passar pela rede . Usaremos o aplicativo de amostra Spring Boot 3.2 para nossas medições e, para todas as funções Lambda, usaremos JAVA_TOOL_OPTIONS: "-XX: TieredCompilation -XX:TieredStopAtLevel=1" e forneceremos a eles 1024 MB de memória Lambda.
Vamos começar explicando como habilitar o AWS SnapStart na função Lambda, pois ele (com preparação na parte superior) fornece o maior potencial de otimização de desempenho do Lambda (especialmente tempos de inicialização a frio). É só uma questão de configuração:
SnapStart: ApplyOn: PublishedVersions
aplicado nas propriedades da função Lambda ou na seção de função global do modelo SAM. Gostaria de me aprofundar em como usar várias técnicas de preparação além do SnpaStart para nosso caso de uso. Expliquei as ideias por trás do priming em meu artigo AWS Lambda SnapStart – Medindo o priming, latência ponta a ponta e tempo de implantação
1) O código para preparação da solicitação do DynamoDB pode ser encontrado aqui.
Esta classe implementa adicionalmente a interface import org.crac.Resource do projeto CraC.
Com esta invocação
Core.getGlobalContext().register(this);A classe
GetProductByIdWithDynamoDBRequestPrimingHandler se registra como recurso CRaC.
Além disso, preparamos a invocação do DynamoDB implementando o método beforeCheckpoint da API CRaC.
@Override public void beforeCheckpoint(org.crac.Context extends Resource> context) throws Exception { productDao.getProduct("0"); }
que invocaremos durante a fase de implantação da função Lambda e antes que o snapshot microVM do Firecracker seja obtido.
2) O código para preparação de toda a solicitação do API Gateway pode ser encontrado aqui.
Esta classe também implementa a interface import org.crac.Resource como no exemplo acima.
Reutilizaremos a técnica feia, que descrevi em meu artigo AWS Lambda SnapStart - Parte 6 Preparando a invocação de solicitação para Java 11 e estruturas Micronaut, Quarkus e Spring Boot. Eu não recomendo usar esta técnica em produção, mas ela demonstra o potencial adicional de reduzir a inicialização a frio usando o priming de toda a solicitação do API Gateway, pré-carregando o mapeamento entre os modelos Spring Boot e Spring Cloud Function e o modelo Lambda executando também o DynamoDB preparação de invocação.
A construção da solicitação do API Gateway de /products/{id} com id igual a 0 A solicitação JSON do API Gateway é semelhante a esta:
private static String getAPIGatewayRequestMultiLine () { return """ { "resource": "/products/{id}", "path": "/products/0", "httpMethod": "GET", "pathParameters": { "id": "0" }, "requestContext": { "identity": { "apiKey": "blabla" } } } """; }
O beforeCheckpoint quando prepara (proxies) toda a solicitação do API Gateway sem passar pela rede usando a classe Spring Cloud Function FunctionInvoker que invoca seu método handleRequest passando o fluxo de entrada da API Solicitação JSON do gateway construída acima assim:
@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()); }
Os resultados do experimento abaixo foram baseados na reprodução de mais de 100 partidas a frio e aproximadamente 100.000 partidas a quente com função Lambda com configuração de memória de 1024 MB durante 1 hora. Para isso usei a ferramenta de teste de carga, ei, mas você pode usar qualquer ferramenta que quiser, como artilharia sem servidor ou Postman.
Eu executei todos esses experimentos com 4 cenários diferentes:
1) Nenhum SnapStart ativado
Em template.yaml use a seguinte configuração:
Handler: org.springframework.cloud.function.adapter.aws.FunctionInvoker::handleRequest #SnapStart: #ApplyOn: PublishedVersions
e precisamos invocar a função Lambda com o nome GetProductByIdWithSpringBoot32SCF que é mapeado para a classe Java GetProductByIdHandler Lambda Handler.
2) SnapStart ativado, mas nenhuma preparação aplicada
Em template.yaml use a seguinte configuração:
Handler: org.springframework.cloud.function.adapter.aws.FunctionInvoker::handleRequest SnapStart: ApplyOn: PublishedVersions
e precisamos invocar a mesma função Lambda com o nome GetProductByIdWithSpringBoot32SCF que é mapeado para a classe Java GetProductByIdHandler Lambda Handler.
3) SnapStart habilitado com preparação de invocação do DynamoDB
Em template.yaml use a seguinte configuração:
Handler: org.springframework.cloud.function.adapter.aws.FunctionInvoker::handleRequest SnapStart: ApplyOn: PublishedVersions
e precisamos invocar a função Lambda com o nome GetProductByIdWithSpringBoot32SCFAndDynamoDBRequestPriming que é mapeado para a classe Java GetProductByIdWithDynamoDBRequestPrimingHandler Lambda Handler.
4) SnapStart habilitado com preparação/proxy de invocação de solicitação do API Gateway
Em template.yaml use a seguinte configuração:
Handler: org.springframework.cloud.function.adapter.aws.FunctionInvoker::handleRequest SnapStart: ApplyOn: PublishedVersions
e precisamos invocar a função Lambda com nome
GetProductByIdWithSpringBoot32SCFAndWebRequestPriming que é mapeado para a classe Java do manipulador Lambda GetProductByIdWithWebRequestPrimingHandler.
Abreviatura c é para partida a frio e w é para partida a quente.
Hora de início frio (c) e quente (w) em ms:
Número do cenário | cp50 | p75 | cp90 | cp99 | c p99.9 | c máx | w p50 | p75 | p90 | wp99 | w p99.9 | w máx |
---|---|---|---|---|---|---|---|---|---|---|---|---|
SnapStart ativado | 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 ativado, mas nenhuma preparação aplicada | 2006.60 | 2065.61 | 2180.17 | 2604.69 | 2662,60 | 2663.54 | 7,45 | 8h40 | 9,92 | 23.09 | 1354,50 | 1496.46 |
SnapStart habilitado com preparação de invocação do 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 habilitado com preparação de invocação de solicitação do 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 |
Ao ativar o SnapStart apenas na função Lambda, ele reduz significativamente o tempo de inicialização a frio da função Lambda. Ao usar adicionalmente a preparação de invocação do DynamoDB, seremos capazes de obter inicializações a frio apenas um pouco superiores às inicializações a frio descritas em meu artigo AWS SnapStart - Medindo inicializações a frio e a quente com Java 21 usando diferentes configurações de memória onde medimos inicializações a frio e a quente para o Lambda puro funcionar sem o uso de quaisquer estruturas, incluindo configuração de memória de 1024 MB, como em nosso cenário.
Comparando os tempos de inicialização a frio e a quente que medimos com AWS Serverless Java Container no artigo Medindo partidas a frio e a quente com AWS Serverless Java Container e Medindo partidas a frio e a quente com AWS Lambda Web Adaptor, observamos que Spring Cloud Function oferece maior frio tempos de inicialização do que o AWS Lambda Web Adaptor, mas tempos de inicialização a frio bastante comparáveis aos do AWS Serverless Java Container (os resultados variam ligeiramente dependendo dos percentis). Em termos de tempos de início/execução a quente, todas as três abordagens apresentam resultados bastante comparáveis quando se analisa especialmente os percentis abaixo de 99,9.
Isenção de responsabilidade: Todos os recursos fornecidos são parcialmente provenientes da Internet. Se houver qualquer violação de seus direitos autorais ou outros direitos e interesses, explique os motivos detalhados e forneça prova de direitos autorais ou direitos e interesses e envie-a para o e-mail: [email protected]. Nós cuidaremos disso para você o mais rápido possível.
Copyright© 2022 湘ICP备2022001581号-3