测量Java 11 Lambda Cold从Snapstart开始 - 第2部分使用Micronaut框架
#aws #serverless #java #micronaut

简介
该系列中的In the first part一般讨论了该快照,并进行了首次测试,以将Plain Java编写的Lambda与AWS SDK与AWS SDK进行比较,并在启用了Snapstart的情况下为Java版本2进行了比较。我们看到,使快照导致了寒冷的开始时间大大减少。在这一部分中,我们将执行同样的操作,但使用流行的Micronaut框架。

Micronaut框架及其功能
Micronaut Framework是现代的,基于JVM的全栈框架,用于构建模块化,易于测试的微服务和无服务器应用程序。它使我们有可能使用launcher或CLI创建应用程序,提供客户验证,API网关集成,GraAlvm(本机映像)整数,支持Maven und Gradle等等。非常重要的是,Micronaut在编译时处理注释,并且不使用反射,运行时字节代码生成,运行时生成的代理和动态类加载。另一方面,Micronaut不支持MicroProfile

用micronaut编写AWS lambda

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

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

Globals:
  Function:
    Handler: io.micronaut.function.aws.proxy.MicronautLambdaHandler

通过映射lambda事件定义和匹配控制器Java实现,定义的lambda函数和SAM与代码中的具体实现的绑定(这是我们如何在Micronaut中实现AWS Lambda函数)。

)。

)。

例如GetProductByIdFunction

  GetProductByIdFunction:
    Type: AWS::Serverless::Function
     .....
      Events:
        GetRequestById:
          Type: Api
          Properties:
            RestApiId: !Ref MyApi
            Path: /products/{id}
            Method: get    

匹配的Micronaut控制器实现是

@Controller
public class GetProductByIdController {

  private final ProductDao productDao;

  public GetProductByIdController(ProductDao productDao) {
    this.productDao = productDao;
  }

  @Get("/products/{id}")
  public Optional<Product> getProductById(@PathVariable String id) {
    return productDao.getProduct(id);
  }

}

作为API网关方法“获取”和SAM模板中定义的PATH/PATH/PATER/{ID}在控制器中匹配Micronaut @get(“/products/{id}”)。 Micronaut提供了自己的一组注释,例如@controller,@get,@put,@delete,@pathvarible,可帮助我们编写基于HTTP/REST的应用程序。处理此类注释与春季Web或Spring Boot注释非常相似。值得注意的是,控制器实现本身不包含对AWS SDK lambda运行时API类(例如requestHandler和apigatewayproxyrequestevent)的任何依赖性,因此它也可以移植到其他云提供商(如果我们替换DAO Tier和Dynamodb实现)或可以是可移植用于编写在容器中运行的微服务。那么,我们如何让我们知道,我们将以lambda函数为单位运行我们的应用程序?

整个美和魔术发生在pom.xml中,我们定义了一堆微养护依赖项

    <dependency>
      <groupId>io.micronaut.aws</groupId>
      <artifactId>micronaut-function-aws-api-proxy</artifactId>
      <scope>compile</scope>
    </dependency>
...

使用AWS SAM模板中定义的Micronautlambdaruntime功能处理程序

  Globals:
  Function:
    Handler: io.micronaut.function.aws.proxy.MicronautLambdaHandler 

将所有内容连接在一起,生成AWS lambda函数,从AWS API网关收集事件。

测量冷启动

让我们给出GetProductById lambda功能1024 MB的内存,并首先测量其冷启动,而无需启用其快照。 CloudWatch Logs Insights查询/aws/lambda/getProductbyIdWithMicronAut日志组的查询是

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

这是结果:

p50 5401.69
P90 5747.15
P99 5786.1

如果我们将这些results与AWS lambda与普通Java进行比较(以及Java版本2版的AWS SDK),我们会注意到,使用Micronaut框架,平均冷启动从4,5秒增加到5.4秒。

现在,让我们启用Snapstart getProductById lambda像这样的功能

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

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

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

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

然后冷启动看起来像这个

p50 1468.18
P90 1595.61
P99 1641.23

如果我们将这些results与AWS Lambda与Plain Java(和Java版本2版的AWS SDK)与SnapStart Enbled进行了比较,我们会注意到,使用Micronaut框架,平均冷启动仅从1,27稍微增加到1.47秒。

结论和下一步
在这篇博客文章中,我们研究了Micronaut框架,并学会了如何编写AWS Lambda功能,该功能从AWS API Gateway接收该事件。我们还测量了冷启动,并没有启用快照。尤其是在启用快照的情况下,与用普通Java编写的lambda相比,冷启动仅略高。随着Micronaut框架通过提供许多功能(请参见上面的列表)提高了开发人员的生产率,因此值得考虑使用它。在系列的下一部分中,我们将探索Quarkus编写lambda功能,并在有没有启用Snapsart的情况下测量冷启动。