测量Java 11 Lambda Cold从Snapstart开始 - 第3部分使用Quarkus框架
#aws #serverless #java #quarkus

介绍

firstsecond系列的一部分中,我们讨论了该快照,并进行了第一个测试,并进行了第一个测试,比较了用Plina Java与AWS SDK与Java版本2的lambda进行的冷启动,并使用Micronaut框架使用Micronaut框架,没有SnapStart已启用。我们看到,在这两种情况下,使快照能够大大减少了寒冷的开始时间。在本系列的这一部分中,我们将测量使用Quarkus作为另一个流行的Java框架的快照的性能。

Quarkus框架及其功能

Quarkus Framework是kubernetes本地java堆栈(我个人不理解这个术语:))针对OpenJDK热点和Graalvm量身定制,并根据Breed Java库和标准制作。对我们来说,重要的是,该框架非常适合编写无服务器应用程序。像Micronaut一样,它使我们有可能使用launcher或CLI创建应用程序,提供API网关集成,GRAALVM(本机映像)整数,支持Maven und Gradle等。它还支持MicroProfileFunqy用于多云解决方案。它还在编译时处理注释,并且不使用反射,运行时字节代码生成,生成的运行时代理和动态类加载。

用quarkus编写AWS Lambda

我们将使用与本系列的前面部分相同的应用程序,但是我们将其重写以使用Quarkus Framework。可以找到此示例应用程序的代码。它提供AWS API网关和2个Lambda功能:“ CreateProduct”和“ GetProductById”。产品存储在Amazon DynamoDB中。我们将使用AWS无服务器应用程序模型(AWS SAM)作为代码。

让我们看如何用Quarkus实施它。在AWS SAM模板(template.yaml)中,我们将AWS lambda功能处理程序指向通用的QuarkusStreamHandler实现:

Globals:
  Function:
    Handler: io.quarkus.amazon.lambda.runtime.QuarkusStreamHandler::handleRequest

来自依赖性

       <dependency>
            <groupId>io.quarkus</groupId>
            <artifactId>quarkus-amazon-lambda</artifactId>
        </dependency>

pom.xml中宣布。

Quarkus支持春季启动注释,例如@RestController,@getMapping,@postmapping,@pathparam以及AWS Java SDK以及Microprofile和Quarkus拥有的注释。在我们的示例中,我们将使用后者。

这就是GetProductById lambda函数实现的样子:

@Named("getProductById")
public class GetProductByIdHandler implements RequestHandler<APIGatewayProxyRequestEvent, Optional<Product>> {
      private final ProductDao productDao = new DynamoProductDao();

      @Override
      public Optional<Product> handleRequest(APIGatewayProxyRequestEvent event, Context context) {
            String id = event.getPathParameters().get("id");
            return productDao.getProduct(id);
}

我们还必须用@RegisterForeflection和@ApplicationsCoped注释来声明产品bean

lambda函数定义与代码之间的映射是通过以下两个步骤完成的:

1)设置Quarkus_lambda_handler环境变量的值AWS SAM模板(template.yaml)

  GetProductByIdFunction:
    Type: AWS::Serverless::Function
.....
      Environment:
        Variables:
          QUARKUS_LAMBDA_HANDLER: getProductById

2)quarkus_lambda_handler环境变量的值(在这种情况下为getProductById)应与lambda函数处理程序中的@Named注释值匹配。

@Named("getProductById")
public class GetProductByIdHandler implements RequestHandler<APIGatewayProxyRequestEvent, Optional<Product>> {

....

QuarkusStreamHandler将所有内容连接在一起。因此,可以在同一SAM模板中定义多个lambda函数。

测量寒冷开始

让我们给出GetProductById lambda功能1024 MB的内存,并首先测量其冷启动,而无需启用其快照。 CloudWatch Logs Insights查询/aws/lambda/getProductbyIdwithquarkus log group for IT

filter @type="REPORT" | fields greatest(@initDuration, 0) + @duration as duration, ispresent(@initDuration) as coldStart| stats count(*) as count,
pct(duration, 50) as p50,
pct(duration, 90) as p90,
pct(duration, 99) as p99,
max(duration) as max by coldStart

这是在同一lambda版本中经历100个冷启动后的结果:

p50 3164.19
P90 3262.57
P99 3823.99

如果我们将这些指标与AWS Lambda with plain Java(以及Java版本2版本的AWS SDK)进行比较,并且与Micronaut进行了比较,我们会注意到使用Quarkus Framework的寒冷开始是最低的。我将在单独的文章中探讨其原因,但是我可以假设这是因为Amazon DynamoDB通信所需的非常完善的HTTP客户端。

由于版本2.15.0。 Quarkus officially supports Lambda SnapStart 。这意味着现在我们可以在Quarkus编写的lambda函数中实现CRaC (Coordinated Restore at Checkpoint) API,以进一步降低寒冷的开始(这将是单独的文章的主题)。
让我们启用snapstart getProductById lambda

Image description或直接在SAM template中。

在SAM模板中的此功能上定义 autopublishalias
也很重要

  GetProductByIdFunction:
    Type: AWS::Serverless::Function
    Properties:
      FunctionName: GetProductByIdWithQuarkus
      AutoPublishAlias: liveVersion
...

我们只能使用snapstart on published function versions and aliases that point to versions。在这种情况下,别名总是默认指向最新版本。 CloudWatch Logs Insights查询/aws/lambda/getProductbyIdwithquarkus log group for IT

filter @type = "REPORT"
  | parse @message /Restore Duration: (?<restoreDuration>.*) ms/
  | stats
count(*) as invocations,
pct(@duration+coalesce(@initDuration,0)+coalesce(restoreDuration,0), 50) as p50,
pct(@duration+coalesce(@initDuration,0)+coalesce(restoreDuration,0), 90) as p90,
pct(@duration+coalesce(@initDuration,0)+coalesce(restoreDuration,0), 99) as p99
group by function, (ispresent(@initDuration) or ispresent(restoreDuration)) as coldstart
  | sort by coldstart desc

这是在同一lambda版本中经历100个冷启动后的结果:

p50 1337.16
P90 1374.76
P99 1473.87

如果我们将这些指标与AWS lambda与Plain Java(以及Java版本2版的AWS SDK)和Micronaut Framework与SnapStart Enbled进行了比较,我们会注意到,使用Micronaut框架使用Quarkus的平均冷启动与第一个相当可比性比后者更好。如果我们使用GRAALVM本机映像编译应用程序,并将我们的lambda作为自定义运行时(如果本文(如果本文)超出范围),我们可以将冷启动进一步降低到450至550ms之间,请参阅measurements以获取可比的应用程序。

结论和下一步

在这篇博客文章中,我们研究了Quarkus框架,并学会了如何编写AWS lambda功能。我们还测量了以下情况下的冷开端,也没有为我们的方案启用快照:Lambda从Amazon API网关接收了该事件,并从Amazon Dynampodb读取项目。与普通AWS SDK版本2 lambda功能和无需快照的Micronaut框架相比,Quarkus表现出最低的寒冷开始。随着Snapstart启用了Quarkus的冷启动比Micronaut更好,并且仅在Plain AWS SDK版本2 Lambda功能之后稍微稍稍后面。我个人可以建议使用Quarkus。众所周知的编程模型是一个巨大的生产力提升。我将写一篇有关不同框架的内存消耗的单独文章,并更深入地研究不同的HTTP客户的选择如何影响寒冷的开始时间。

在系列的下一部分中,我们将探索Spring Boot编写lambda功能,并在没有启用Snapsart的情况下测量冷点。