使用 .zip 或 JAR 文件归档部署 Java Lambda 函数 - Amazon Lambda
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

使用 .zip 或 JAR 文件归档部署 Java Lambda 函数

您的 Amazon Lambda 函数代码由脚本或编译的程序及其依赖项组成。您可以使用部署程序包将函数代码部署到 Lambda。Lambda 支持两种类型的部署程序包:容器镜像和 .zip 文件归档。

本页将介绍如何将部署程序包创建为 .zip 文件或 Jar 文件,然后使用该部署程序包通过 Amazon Lambda (Amazon Command Line Interface) 将函数代码部署到 Amazon CLI。

先决条件

Amazon CLI 是一种开源工具,让您能够在命令行 Shell 中使用命令与 Amazon 服务进行交互。要完成本节中的步骤,您必须拥有 Amazon CLI 版本 2

工具和库

Lambda 提供以下适用于 Java 函数的库:

这些库可通过 Maven 中央存储库获得。将它们添加到您的构建定义中,如下所示:

Gradle
dependencies { implementation 'com.amazonaws:aws-lambda-java-core:1.2.2' implementation 'com.amazonaws:aws-lambda-java-events:3.11.1' runtimeOnly 'com.amazonaws:aws-lambda-java-log4j2:1.5.1' }
Maven
<dependencies> <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-core</artifactId> <version>1.2.2</version> </dependency> <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-events</artifactId> <version>3.11.1</version> </dependency> <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-log4j2</artifactId> <version>1.5.1</version> </dependency> </dependencies>

要创建部署程序包,请将函数代码和依赖项编译成单个 .zip 文件或 Java 存档 (JAR) 文件。对于 Gradle,请使用 Zip 构建类型。对于 Apache Maven,请使用 Maven Shade 插件。要上传部署包,请使用 Lambda 控制台、Lambda API 或 Amazon Serverless Application Model(Amazon SAM)。

注意

为了减小部署程序包的大小,请将函数的依赖项打包到层中。层可让您独立管理依赖项,可供多个函数使用,并可与其他账户共享。有关更多信息,请参阅 使用层管理 Lambda 依赖项

使用 Gradle 构建部署程序包

要创建包含 Gradle 中函数代码和依赖项的部署包,请使用 Zip 构建类型。这是来自完整示例 build.gradle 文件的示例:

例 build.gradle – 构建任务
task buildZip(type: Zip) { into('lib') { from(jar) from(configurations.runtimeClasspath) } }

此构建配置在 build/distributions 目录中生成部署程序包。在 into('lib') 语句中,jar 任务将包含主类的 jar 归档组装到名为 lib 的文件夹中。此外,configurations.runtimeClassPath 任务将依赖项库从构建的类路径复制到同一 lib 文件夹中。

例 build.gradle – 依赖项
dependencies { ... implementation 'com.amazonaws:aws-lambda-java-core:1.2.2' implementation 'com.amazonaws:aws-lambda-java-events:3.11.1' implementation 'org.apache.logging.log4j:log4j-api:2.17.1' implementation 'org.apache.logging.log4j:log4j-core:2.17.1' runtimeOnly 'org.apache.logging.log4j:log4j-slf4j18-impl:2.17.1' runtimeOnly 'com.amazonaws:aws-lambda-java-log4j2:1.5.1' ... }

Lambda 按 Unicode 字母顺序加载 JAR 文件。如果 lib 目录中的多个 JAR 文件包含相同的类,则使用第一个。可以使用以下 shell 脚本来识别重复类:

例 test-zip.sh
mkdir -p expanded unzip path/to/my/function.zip -d expanded find ./expanded/lib -name '*.jar' | xargs -n1 zipinfo -1 | grep '.*.class' | sort | uniq -c | sort

为依赖项创建 Java 层

注意

在 Java 等编译语言中将层与函数结合使用,不一定会产生与使用 Python 等解释性语言的相同效果。由于 Java 是一种编译语言,因此函数仍然需要在初始化阶段将所有共享程序集手动加载到内存中,而这可能会增加冷启动时间。我们建议您改为在编译时包含任何共享代码,以充分利用内置编译器的优化。

本部分中的说明旨在向您展示如何将依赖项包含在层中。有关如何将依赖项包含在部署包中的说明,请参阅 使用 Gradle 构建部署程序包 或 使用 Maven 构建部署程序包

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

  • java/lib (CLASSPATH)

例如,层.zip 文件结构可能如下所示:

jackson.zip └ java/lib/jackson-core-2.2.3.jar

此外,Lambda 会自动检测 /opt/lib 目录中的任何库,以及 /opt/bin 目录中的任何二进制文件。为确保 Lambda 正确获取层内容,还可以创建包含以下结构的层:

custom-layer.zip └ lib | lib_1 | lib_2 └ bin | bin_1 | bin_2

打包层后,请参阅 在 Lambda 中创建和删除层 和 向函数添加层 以完成层设置。

使用 Maven 构建部署程序包

要使用 Maven 构建部署程序包,请使用 Maven Shade 插件。该插件创建一个包含编译的函数代码及其所有依赖项的 JAR 文件。

例 pom.xml – 插件配置
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.2.2</version> <configuration> <createDependencyReducedPom>false</createDependencyReducedPom> </configuration> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> </execution> </executions> </plugin>

要构建部署程序包,请使用 mvn package 命令。

[INFO] Scanning for projects... [INFO] -----------------------< com.example:java-maven >----------------------- [INFO] Building java-maven-function 1.0-SNAPSHOT [INFO] --------------------------------[ jar ]--------------------------------- ... [INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ java-maven --- [INFO] Building jar: target/java-maven-1.0-SNAPSHOT.jar [INFO] [INFO] --- maven-shade-plugin:3.2.2:shade (default) @ java-maven --- [INFO] Including com.amazonaws:aws-lambda-java-core:jar:1.2.2 in the shaded jar. [INFO] Including com.amazonaws:aws-lambda-java-events:jar:3.11.1 in the shaded jar. [INFO] Including joda-time:joda-time:jar:2.6 in the shaded jar. [INFO] Including com.google.code.gson:gson:jar:2.8.6 in the shaded jar. [INFO] Replacing original artifact with shaded artifact. [INFO] Replacing target/java-maven-1.0-SNAPSHOT.jar with target/java-maven-1.0-SNAPSHOT-shaded.jar [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 8.321 s [INFO] Finished at: 2020-03-03T09:07:19Z [INFO] ------------------------------------------------------------------------

此命令在 target 目录中生成 JAR 文件。

注意

如果您使用的是多版本 JAR(MRJAR),则必须在 lib 目录中包含 MRJAR(即由 Maven Shade 插件生成的着色 JAR),并在将部署包上传到 Lambda 之前对其进行压缩。否则,Lambda 可能无法正确解压 JAR 文件,从而导致 MANIFEST.MF 文件被忽略。

如果您使用 Appender 库 (aws-lambda-java-log4j2),还必须为 Maven Shade 插件配置一个转换器。转换器库合并同时出现在 Appender 库和 Log4j 中的缓存文件的版本。

例 pom.xml – 具有 Log4j 2 Appender 的插件配置
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.2.2</version> <configuration> <createDependencyReducedPom>false</createDependencyReducedPom> </configuration> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <transformers> <transformer implementation="com.github.edwgiz.maven_shade_plugin.log4j2_cache_transformer.PluginsCacheFileTransformer"> </transformer> </transformers> </configuration> </execution> </executions> <dependencies> <dependency> <groupId>com.github.edwgiz</groupId> <artifactId>maven-shade-plugin.log4j2-cachefile-transformer</artifactId> <version>2.13.0</version> </dependency> </dependencies> </plugin>

使用 Lambda 控制台上传部署包

要创建新函数,必须先在控制台中创建该函数,然后上传您的 .zip 或 JAR 文件。要更新现有函数,请打开函数页面,然后按照相同的步骤添加更新的 .zip 或 JAR 文件。

如果您的部署包文件小于 50MB,则可以通过直接从本地计算机上传该文件来创建或更新函数。对于大于 50MB 的 .zip 或 JAR 文件,必须首先将您的程序包上传到 Amazon S3 存储桶。有关如何使用 Amazon Web Services Management Console 将文件上传到 Amazon S3 存储桶的说明,请参阅 Amazon S3 入门。要使用 Amazon CLI 上传文件,请参阅《Amazon CLI 用户指南》中的移动对象

注意

您无法更改现有函数的部署包类型(.zip 或容器映像)。例如,您无法将容器映像函数转换为使用 .zip 文件归档。您必须创建新函数。

创建新函数(控制台)
  1. 打开 Lambda 控制台的“函数”页面,然后选择创建函数

  2. 选择从头开始创作

  3. 基本信息中,执行以下操作:

    1. 对于函数名称,输入函数的名称。

    2. 对于运行时系统,选择要使用的运行时系统。

    3. (可选)对于架构,选择要用于函数的指令集架构。默认架构为 x86_64。确保您的函数的 .zip 部署包与您选择的指令集架构兼容。

  4. (可选)在 Permissions(权限)下,展开 Change default execution role(更改默认执行角色)。您可以创建新的执行角色,也可以使用现有角色。

  5. 选择 Create function (创建函数)。Lambda 使用您选择的运行时系统创建基本“Hello world”函数。

从本地计算机上传 .zip 或 JAR 归档(控制台)
  1. 在 Lambda 控制台的“函数”页面中,选择要为其上传 .zip 或 JAR 文件的函数。

  2. 选择代码选项卡。

  3. 代码源窗格中,选择上传自

  4. 选择 .zip 或 .jar 文件

  5. 要上传 .zip 或 JAR 文件,请执行以下操作:

    1. 选择上传,然后在文件选择器中选择您的 .zip 或 JAR 文件。

    2. 选择打开

    3. 选择保存

从 Amazon S3 存储桶上传 .zip 或 JAR 归档(控制台)
  1. 在 Lambda 控制台的“函数”页面中,选择要为其上传新 .zip 或 JAR 文件的函数。

  2. 选择代码选项卡。

  3. 代码源窗格中,选择上传自

  4. 选择 Amazon S3 位置

  5. 粘贴 .zip 文件的 Amazon S3 链接 URL,然后选择保存

使用 Amazon CLI 上传部署包

您可以使用 Amazon CLI 创建新函数或使用 .zip 或 JAR 文件更新现有函数。使用 create-functionupdate-function-code 命令部署 .zip 或 JAR 程序包。如果您的文件小于 50MB,则可以从本地生成计算机上的文件位置上传程序包。对于较大的文件,必须从 Amazon S3 存储桶上传 .zip 或 JAR 程序包。有关如何使用 Amazon CLI 将文件上传到 Amazon S3 存储桶的说明,请参阅《Amazon CLI 用户指南》中的移动对象

注意

如果您使用 Amazon CLI 从 Amazon S3 存储桶上传 .zip 或 JAR 文件,则该存储桶必须与您的函数位于同一个 Amazon Web Services 区域中。

要通过 Amazon CLI 使用 .zip 或 JAR 文件创建新函数,则必须指定以下内容:

  • 函数的名称 (--function-name)

  • 函数的运行时系统 (--runtime)

  • 函数的执行角色 (--role) 的 Amazon 资源名称(ARN)

  • 函数代码 (--handler) 中处理程序方法的名称

还必须指定 .zip 或 JAR 文件的位置。如果 .zip 或 JAR 文件位于本地生成计算机上的文件夹中,请使用 --zip-file 选项指定文件路径,如以下示例命令所示。

aws lambda create-function --function-name myFunction \ --runtime java21 --handler example.handler \ --role arn:aws:iam::123456789012:role/service-role/my-lambda-role \ --zip-file fileb://myFunction.zip

要指定 .zip 文件在 Amazon S3 存储桶中的位置,请使用 --code 选项,如以下示例命令所示。您只需对版本控制对象使用 S3ObjectVersion 参数。

aws lambda create-function --function-name myFunction \ --runtime java21 --handler example.handler \ --role arn:aws:iam::123456789012:role/service-role/my-lambda-role \ --code S3Bucket=amzn-s3-demo-bucket,S3Key=myFileName.zip,S3ObjectVersion=myObjectVersion

要使用 CLI 更新现有函数,请使用 --function-name 参数指定函数的名称。您还必须指定要用于更新函数代码的 .zip 文件的位置。如果 .zip 文件位于本地生成计算机上的文件夹中,请使用 --zip-file 选项指定文件路径,如以下示例命令所示。

aws lambda update-function-code --function-name myFunction \ --zip-file fileb://myFunction.zip

要指定 .zip 文件在 Amazon S3 存储桶中的位置,请使用 --s3-bucket--s3-key 选项,如以下示例命令所示。您只需对版本控制对象使用 --s3-object-version 参数。

aws lambda update-function-code --function-name myFunction \ --s3-bucket amzn-s3-demo-bucket --s3-key myFileName.zip --s3-object-version myObject Version

使用 Amazon SAM 上传部署程序包

您可以使用 Amazon SAM 自动部署函数代码、配置和依赖项。Amazon SAM 是 Amazon CloudFormation 的一个扩展,它提供用于定义无服务器应用程序的简化语法。以下示例模板在 Gradle 使用的 build/distributions 目录中定义了一个包含部署程序包的函数。

例 template.yml
AWSTemplateFormatVersion: '2010-09-09' Transform: 'AWS::Serverless-2016-10-31' Description: An Amazon Lambda application that calls the Lambda API. Resources: function: Type: AWS::Serverless::Function Properties: CodeUri: build/distributions/java-basic.zip Handler: example.Handler Runtime: java21 Description: Java function MemorySize: 512 Timeout: 10 # Function's execution role Policies: - AWSLambdaBasicExecutionRole - AWSLambda_ReadOnlyAccess - AWSXrayWriteOnlyAccess - AWSLambdaVPCAccessExecutionRole Tracing: Active

要创建函数,请使用 packagedeploy 命令。这些命令是对 Amazon CLI 的自定义。它们包装其他命令以将部署程序包上载到 Amazon S3,使用对象 URI 重写模板,然后更新函数的代码。

以下示例脚本运行 Gradle 构建并上传其创建的部署程序包。它在您第一次运行它时创建一个 Amazon CloudFormation 堆栈。如果堆栈已经存在,脚本会更新它。

例 deploy.sh
#!/bin/bash set -eo pipefail aws cloudformation package --template-file template.yml --s3-bucket MY_BUCKET --output-template-file out.yml aws cloudformation deploy --template-file out.yml --stack-name java-basic --capabilities CAPABILITY_NAMED_IAM

有关完整的工作示例,请参阅以下示例应用程序。

Java 中的 Lambda 应用程序示例
  • java17-examples:这是一种 Java 函数,演示如何使用 Java 记录来表示输入事件数据对象。

  • java-basic – 具有单元测试和变量日志记录配置的最小 Java 函数的集合。

  • java-events – Java 函数的集合,其中包含用于处理来自 Amazon API Gateway、Amazon SQS 和 Amazon Kinesis 等各种服务的事件的框架代码。这些函数使用最新版本的 aws-lambda-events 库(3.0.0 及更新版本)。这些示例不需要 Amazon 开发工具包作为依赖项。

  • s3-java – 此 Java 函数可处理来自 Amazon S3 的通知事件,并使用 Java 类库(JCL)从上传的图像文件创建缩略图。

  • 自定义序列化 –如何使用 fastJson、Gson、Moshi 和 jackson-jr 等常用库实现自定义序列化的示例。

  • 使用 API Gateway 调用 Lambda 函数 – Java 函数,用于扫描包含员工信息的 Amazon DynamoDB 表。然后,该函数使用 Amazon Simple Notification Service 向员工发送短信,祝贺他们工作周年纪念日快乐。此示例使用 API Gateway 调用函数。