使用 Java Lambda 函数的层 - AWS Lambda

使用 Java Lambda 函数的层

Lambda 层是包含补充代码或数据的 .zip 文件存档。层通常包含库依赖项、自定义运行时系统或配置文件。创建层涉及三个常见步骤:

  1. 打包层内容。此步骤需要创建 .zip 文件存档,其中包含要在函数中使用的依赖项。

  2. 在 Lambda 中创建层。

  3. 将层添加到函数。

本主题包含有关如何正确打包并创建具有外部库依赖项的 Java Lambda 层的步骤和指南。

先决条件

要完成本部分中的步骤,您必须满足以下条件:

注意

确保 Maven 引用的 Java 版本与要部署的函数的 Java 版本相同。例如,若要部署 Java 21 函数,mvn -v 命令应在输出中列出 Java 版本 21:

Apache Maven 3.8.6 ... Java version: 21.0.2, vendor: Oracle Corporation, runtime: /Library/Java/JavaVirtualMachines/jdk-21.jdk/Contents/Home ...

在整个主题中,我们会引用 awsdocs GitHub 存储库中的 layer-java 示例应用程序。该应用程序包含用于下载依赖项并生成层的脚本。该应用程序还包含相应的函数,函数使用来自层的依赖项。创建层后,即可部署并调用相应的函数来验证一切是否正常运行。由于使用 Java 21 运行时系统来运行这些函数,因此这些层还必须与 Java 21 兼容。

layer-java 示例应用程序在两个子目录中包含一个示例。layer 目录包含用于定义层依赖项的 pom.xml 文件,以及用于生成层的脚本。function 目录包含示例函数,用于帮助测试该层是否正常工作。本教程将演示如何创建并打包该层。

Java 层与 Amazon Linux 的兼容性

创建层的第一步是将所有层内容捆绑到.zip 文件存档中。由于 Lambda 函数在 Amazon Linux 上运行,因此层内容必须能够在 Linux 环境中编译和构建。

Java 代码采用独立于平台的设计,即便本地计算机不使用 Linux 环境,您也可以在本地计算机上打包层。将 Java 层上传到 Lambda 后,Java 层仍将与 Amazon Linux 兼容。

Java 运行时系统的层路径

当您向函数添加层时,Lambda 会将层内容加载到该执行环境的 /opt 目录中。对于每个 Lambda 运行时系统,PATH 变量都包括 /opt 目录中的特定文件夹路径。为确保 PATH 变量能够获取层内容,层 .zip 文件应在以下文件夹路径中具有依赖项:

  • java/lib

例如,您在本教程中创建生成的层.zip 文件具有以下目录结构:

layer_content.zip └ java └ lib └ layer-java-layer-1.0-SNAPSHOT.jar

layer-java-layer-1.0-SNAPSHOT.jar JAR 文件(包含所有必需依赖项的 uber-jar)位于 java/lib 目录中,位置正确。这可确保 Lambda 在函数调用期间可以找到该库。

打包层内容

本示例将以下两个 Java 库打包到单个 JAR 文件中:

  • aws-lambda-java-core:一组在 AWS Lambda 中用于处理 Java 的最小接口定义

  • Jackson:一套特别适用于处理 JSON 的热门数据处理工具。

完成以下步骤,安装并打包层内容。

安装并打包层内容
  1. 克隆 aws-lambda-developer-guide GitHub 存储库,其中包含 sample-apps/layer-java 目录中需要的示例代码。

    git clone https://github.com/awsdocs/aws-lambda-developer-guide.git
  2. 导航到 layer-java 示例应用程序的 layer 目录。此目录包含用于正确创建并打包层的脚本。

    cd aws-lambda-developer-guide/sample-apps/layer-java/layer
  3. 检查 pom.xml 文件。在 <dependencies> 部分,定义要包含在层中的依赖项,即 aws-lambda-java-corejackson-databind 库。您可以更新此文件,纳入要包含在层中的任何依赖项。

    例 pom.xml
    <dependencies> <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-core</artifactId> <version>1.2.3</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.17.0</version> </dependency> </dependencies>
    注意

    pom.xml 文件的 <build> 部分包含两个插件。maven-compiler-plugin 可编译源代码。maven-shade-plugin 可将构件打包到一个 uber-jar 中。

  4. 确保拥有运行这两个脚本的权限。

    chmod 744 1-install.sh && chmod 744 2-package.sh
  5. 使用以下命令运行 1-install.sh 脚本:

    ./1-install.sh

    此脚本在当前目录中运行 mvn clean install。这会在 target/ 目录中创建包含所有必需依赖项的 uber-jar。

    例 1-install.sh
    mvn clean install
  6. 使用以下命令运行 2-package.sh 脚本:

    ./2-package.sh

    此脚本会创建正确打包层内容所需的 java/lib 目录结构。然后,其会将 uber-jar 从 /target 目录复制到新创建的 java/lib 目录中。最后,此脚本会将 java 目录的内容压缩到名为 layer_content.zip 的文件中。这便是层的 .zip 文件。您可以解压缩文件,验证是否包含正确的文件结构,如 Java 运行时系统的层路径部分所示。

    例 2-package.sh
    mkdir java mkdir java/lib cp -r target/layer-java-layer-1.0-SNAPSHOT.jar java/lib/ zip -r layer_content.zip java

创建层

在本部分,您会获取在上一部分中生成的 layer_content.zip 文件,将其作为 Lambda 层上传。您可以使用 AWS Management Console 上传层,也可以通过 AWS Command Line Interface(AWS CLI)使用 Lambda API 上传层。上传层 .zip 文件时,在以下 PublishLayerVersion AWS CLI 命令中,将 java21 指定为兼容的运行时系统,并将 arm64 指定为兼容的架构。

aws lambda publish-layer-version --layer-name java-jackson-layer \ --zip-file fileb://layer_content.zip \ --compatible-runtimes java21 \ --compatible-architectures "arm64"

注意响应中的 LayerVersionArn,与 arn:aws:lambda:us-east-1:123456789012:layer:java-jackson-layer:1 类似。在本教程的下一步中,在将层添加到函数时,您要用到此 Amazon 资源名称(ARN)。

将层添加到函数

在本部分,您要部署在函数代码中使用 Jackson 库的示例 Lambda 函数,然后附加该层。要部署该函数,您需要一个 使用执行角色定义 Lambda 函数权限。如果目前没有执行角色,则按照可折叠部分中的步骤操作。

创建执行角色
  1. 在 IAM 控制台中,打开 Roles(角色)页面

  2. 选择创建角色

  3. 创建具有以下属性的角色。

    • Trusted entity(可信任的实体)– Lambda

    • Permissions(权限)– AWSLambdaBasicExecutionRole

    • Role name(角色名称)– lambda-role

    AWSLambdaBasicExecutionRole 策略具有函数将日志写入 CloudWatch Logs 所需的权限。

Lambda 函数代码接受 Map<String, String> 作为输入,并使用 Jackson 将输入写为 JSON 字符串,然后再将其转换为预定义的 F1Car Java 对象。最后,函数使用 F1Car 对象中的字段来构造函数返回的字符串。

package example; import com.amazonaws.services.lambda.runtime.Context; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; import java.util.Map; public class Handler { public String handleRequest(Map<String, String> input, Context context) throws IOException { // Parse the input JSON ObjectMapper objectMapper = new ObjectMapper(); F1Car f1Car = objectMapper.readValue(objectMapper.writeValueAsString(input), F1Car.class); StringBuilder finalString = new StringBuilder(); finalString.append(f1Car.getDriver()); finalString.append(" is a driver for team "); finalString.append(f1Car.getTeam()); return finalString.toString(); } }
部署 Lambda 函数
  1. 导航到 function/ 目录。如果当前在 layer/ 目录中,请运行以下命令:

    cd ../function
  2. 使用以下 Maven 命令构建项目:

    mvn package

    此命令在名为 layer-java-function-1.0-SNAPSHOT.jartarget/ 目录中生成 JAR 文件。

  3. 部署函数。在以下 AWS CLI 命令中,将 --role 参数替换为执行角色 ARN:

    aws lambda create-function --function-name java_function_with_layer \ --runtime java21 \ --architectures "arm64" \ --handler example.Handler::handleRequest \ --timeout 30 \ --role arn:aws:iam::123456789012:role/lambda-role \ --zip-file fileb://target/layer-java-function-1.0-SNAPSHOT.jar
  4. 接下来,将层附加到函数。在以下 AWS CLI 命令中,将 --layers 参数替换为之前记下的层版本 ARN:

    aws lambda update-function-configuration --function-name java_function_with_layer \ --cli-binary-format raw-in-base64-out \ --layers "arn:aws:lambda:us-east-1:123456789012:layer:java-jackson-layer:1"
  5. 最后,尝试使用以下 AWS CLI 命令调用函数:

    aws lambda invoke --function-name java_function_with_layer \ --cli-binary-format raw-in-base64-out \ --payload '{ "driver": "Max Verstappen", "team": "Red Bull" }' response.json

    应看到类似如下内容的输出:

    { "StatusCode": 200, "ExecutedVersion": "$LATEST" }

    这表示函数能够使用 Jackson 依赖项来正确执行函数。您可以检查输出 response.json 文件是否包含正确的返回字符串:

    "Max Verstappen is a driver for team Red Bull"

除非您想要保留为本教程创建的资源,否则可立即将其删除。通过删除您不再使用的 AWS 资源,可防止您的 AWS 账户 产生不必要的费用。

删除 Lambda 层
  1. 打开 Lambda 控制台的 Layers page(层页面)。

  2. 选择您创建的层。

  3. 选择删除,然后再次选择删除

删除 Lambda 函数
  1. 打开 Lamba 控制台的 Functions(函数)页面

  2. 选择您创建的函数。

  3. 依次选择操作删除

  4. 在文本输入字段中键入 delete,然后选择 Delete(删除)。