使用 AWS CDK 用于 Java Lambda 的 AWS SnapStart

问题描述 投票:0回答:1

我正在尝试使用 Java 11(或 17)AWS CDK 来编排 Lambda。 Lambda 在 JVM 编译和冷启动方面存在严重问题,因此我一直在考虑使用 AWS 提供的较新的 SnapStart 功能。 CDK 推送包含 SnapStart 组件的 CloudFormation 堆栈、新版本的 Lambda 以及该版本的别名。这些都是 SnapStart 的必要要求。

使用 SnapStart 配置和别名创建 CDK Lambda

       //Lambda Function
        String lambdaHandlerName = "com.handlers.lambdaHandler::handleRequest";
        IRole role5 = Role.fromRoleName(this, "Lambda", "LambdaRole");

        Function lambdaFunction = new Function(this, "lambdaFunction", getLambdaFunctionProps(lambdaEnvMap, lambdaHandlerName, role5, "lambdaHandler"));
        dynamoTable.grantReadData(lambdaFunction);

        //SnapStart Config
        lambdaFunction.getCurrentVersion().addAlias("snap", AliasOptions.builder()
                .description("Alias version for snap resources")
                .build());
        CfnFunction lambdaCfnFunction = (CfnFunction) lambdaCfnFunction.getNode().getDefaultChild();
        lambdaCfnFunction.setSnapStart(CfnFunction.SnapStartProperty.builder()
                .applyOn("PublishedVersions")
                .build());

在 AWS 控制台本身内,似乎已为设置为“PublishedVersions”的基本功能启用了 SnapStart。

SnapStart enabled on base function

当我查看最近发布的版本时,我发现它也启用了 SnapStart。

SnapStart enabled on Version

但是,当我通过 API Gateway(配置为正确版本的 Lambda)调用 Lambda 函数时,SnapStart 似乎不适用于该函数,并且我的冷启动时间仍然约为 2 秒。

我还尝试实现 AWS 建议的 SnapStart 运行时挂钩到 Lambda 函数处理程序本身:

SnapStart 的处理程序运行时挂钩

   public GetAllQuotesHandler() {
        Core.getGlobalContext().register(this);
    }

    @Override
    public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent event, Context context) {
      ...
    }

    
    @Override
    public void beforeCheckpoint(org.crac.Context<? extends Resource> context) throws Exception {
        this.dynamoDb.close();
        System.out.println("Before");
    }

    @Override
    public void afterRestore(org.crac.Context<? extends Resource> context) throws Exception {
        System.out.println("After");
    }
}

我不确定我的配置有什么问题,有什么建议吗?

我希望 AWS Lambda 能够使用 SnapStart 并调用我的 Lambda 函数,而无需冷启动。

java aws-lambda aws-api-gateway aws-cdk
1个回答
0
投票

到目前为止,您似乎已经在 lambda 配置上配置了 SnapStart,这本身将使您的冷启动时间略有减少。为了完全减少冷启动时间,您需要在创建 lambda 版本时拍摄快照之前“准备”JVM 的状态。

beforeCheckpoint
运行时钩子是在拍摄 JVM/容器快照之前调用的。通过从此方法中调用代码单元,JVM 将解释这些单元存储的字节码 .class 文件,并使用 JIT 编译将它们编译为本机机器代码。这将保存在快照中,因此当首次为实际请求调用 lambda 时,不需要解释该字节码。

使用代码执行此操作的最简单方法是从

handleRequest(…)
方法中调用
beforeCheckpoint(…)
方法,并使用
APIGatewayProxyRequestEvent
来完成您拥有的任何业务逻辑,并实际调用 dynamoDb 客户端。理想情况下,您将调用尽可能多的代码,以便在拍摄快照之前对其进行解释。

所以它看起来像这样:

public class GetAllQuotesHandler {

   public GetAllQuotesHandler() {
        Core.getGlobalContext().register(this);
    }

    @Override
    public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent event, Context context) {
      ...
    }

    // Call the handler method with a test event. 
    @Override
    public void beforeCheckpoint(org.crac.Context<? extends Resource> context) throws Exception {
        log.info("beforeCheckpoint({}) called.", context);
        
        APIGatewayProxyRequestEvent testEvent = new APIGatewayProxyRequestEvent().withBody("string body").withHttpMethod("POST");
        try {
            handleRequest(testEvent, null);
        } catch (Exception ex) {
            log.info("Error executing beforeCheckpoint({})", testEvent);
        }
    }

    @Override
    public void afterRestore(org.crac.Context<? extends Resource> context) throws Exception {
        // not used
    }
}

如果您的函数使用 aws SDK 调用其他 AWS 资源,您还需要使用不同的凭证提供程序:

ContainerCredentialsProvider.builder().build();

因为这些资源需要最新的凭据。您无法使用环境变量凭据提供程序,因为这些凭据仅在创建版本时才会被调用,并且它们最终将过期。这是因为无参数构造函数只会在创建版本时调用一次,而不是每次在新的执行环境中调用 lambda 函数时调用。

© www.soinside.com 2019 - 2024. All rights reserved.