使用 .zip 或 JAR 封存檔部署 Java Lambda 函數 - AWS Lambda

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

使用 .zip 或 JAR 封存檔部署 Java Lambda 函數

你的 AWS Lambda 函數的代碼由腳本或編譯的程序及其依賴關係組成。使用部署套件將函數程式碼部署到 Lambda。Lambda 支援兩種類型的部署套件:容器映像和 .zip 封存檔。

本頁說明如何將部署套件建立為 .zip 檔案或 Jar 檔案,然後使用部署套件將函數程式碼部署至 AWS Lambda 使用 AWS Command Line Interface (AWS CLI)。

必要條件

這 AWS CLI 是一種開放原始碼工具,可讓您使用命令列殼層中的命令與 AWS 服務互動。若要完成本節中的步驟,您必須執行下列各項:

工具與程式庫

Lambda 提供下列適用於 Java 函數的程式庫:

這些程式庫可透過 Maven Central Repository 取得。請將它們新增到您的建置定義中,如下所示︰

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 或 AWS Serverless Application Model (AWS 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 檔案包含相同類別,則會使用第一個 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 是編譯語言,因此您的函數仍須在 init 階段將任何共用組件手動載入記憶體中,這可能會增加冷啟動時間。相反地,建議您在編譯時加入任何共用程式碼,利用任何內建的編譯器最佳化功能。

本節中的指示說明如何在層中包含相依項。如需如何在部署套件中包含相依項的指示,請參閱使用 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 檔案被忽略。

如果您使用附加器程式庫 (aws-lambda-java-log4j2),則還必須配置 Maven Shade 外掛程式的轉換器。轉換器程式庫會合併出現在附加器程式庫和 Log4j 中快取檔案的版本。

範例 pom.xml - 具備 Log4j 2 附加器的外掛程式組態
<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 檔案。

如果您的部署套件檔案小於 50 MB,您可以透過直接從本機電腦上傳檔案來建立或更新函數。若 .zip 或 JAR 檔案大於 50 MB,您必須先將套件上傳至 Amazon S3 儲存貯體。如需有關如何使用將檔案上傳到 Amazon S3 儲存貯體的指示 AWS Management Console,請參閱開始使用 Amazon S3。若要使用上載檔案 AWS CLI,請參閱《使用指南》中的AWS CLI 〈移動物件

注意

您無法變更現有函數的部署套件類型 (.zip 或容器映像檔)。例如,您無法將容器映像函數轉換為使用 .zip 檔案封存。您必須建立新的函數。

若要建立新的函數 (主控台)
  1. 開啟 Lambda 主控台的函數頁面,然後選擇建立函數

  2. 選擇 Author from scratch (從頭開始撰寫)。

  3. 基本資訊下,請執行下列動作:

    1. 函數名稱中輸入函數名稱。

    2. 執行期中選取要使用的執行期。

    3. (選用) 在架構中選擇要用於函數的指令集架構。預設架構值為 x86_64。請確定函數的 .zip 部署套件與您選取的指令集架構相容。

  4. (選用) 在 許可 下,展開 變更預設執行角色 。您可建立新的執行角色,或使用現有的角色。

  5. 選擇建立函數。Lambda 會使用您選擇的執行期建立一個基本的「Hello world」函數。

若要從本機電腦上傳 .zip 或 JAR 封存檔 (主控台)
  1. 在 Lambda 主控台的函數頁面中選擇要上傳 .zip 或 JAR 檔案的函數。

  2. 選取程式碼索引標籤。

  3. 程式碼來源窗格中選擇上傳來源

  4. 選擇 .zip 或 .jar 檔案

  5. 若要上傳 .zip 或 JAR 檔案,請執行下列操作:

    1. 選取上傳,然後在檔案選擇器中選取您的 .zip 或 JAR 檔案。

    2. 選擇 Open (開啟)。

    3. 選擇儲存

若要從 Amazon S3 儲存貯體上傳 .zip 或 JAR 封存檔 (控制台)
  1. 在 Lambda 主控台的函數頁面中選擇要上傳新 .zip 或 JAR 檔案的函數。

  2. 選取程式碼索引標籤。

  3. 程式碼來源窗格中選擇上傳來源

  4. 選擇 Amazon S3 位置

  5. 貼上 .zip 檔案的 Amazon S3 連結 URL,然後選擇儲存

上傳部署套件 AWS CLI

您可以使用 AWS CLI 建立新函數,或使用 .zip 或 JAR 檔案更新現有函數。使用建立函數update-function-code命令來部署您的 .zip 或 JAR 套件。如果您的檔案小於 50 MB,則可以從本機建置電腦的檔案位置上傳套件。若檔案較大,則必須先從 Amazon S3 儲存貯體上傳 .zip 或 JAR 套件。如需有關如何使用將檔案上傳到 Amazon S3 儲存貯體的指示 AWS CLI,請參閱使用AWS CLI 者指南中的移動物件

注意

如果您使用從 Amazon S3 儲存貯體上傳 .zip 或 JAR 檔案 AWS CLI,則該儲存貯體必須與您的函數位於 AWS 區域 相同的位置。

若要使用 .zip 或 JAR 檔案與建立新函數 AWS CLI,您必須指定下列項目:

  • 函數名稱 (--function-name)

  • 函數的執行期 (--runtime)

  • 函數執行角色的 Amazon Resource Name (ARN) (--role)

  • 函數程式碼中處理常式方法的名稱 (--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

若要在 Amazon S3 儲存貯體中指定 .zip 檔案的位置,請使用如下列範例命令所示的 --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=DOC-EXAMPLE-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

若要在 Amazon S3 儲存貯體中指定 .zip 檔案的位置,請使用如下列範例命令所示的 --s3-bucket 和 --s3-key 選項。您只需針對版本控制的物件使用 --s3-object-version 參數。

aws lambda update-function-code --function-name myFunction \ --s3-bucket DOC-EXAMPLE-BUCKET --s3-key myFileName.zip --s3-object-version myObject Version

上傳部署套件 AWS SAM

您可以使 AWS SAM 用自動化函數程式碼、組態和相依性的部署。 AWS SAM 是的延伸 AWS CloudFormation ,可提供簡化語法來定義無伺服器應用程式。下列範例範本會透過在 Gradle 使用的 build/distributions 目錄中的部署套件定義函數︰

範例 template.yml
AWSTemplateFormatVersion: '2010-09-09' Transform: 'AWS::Serverless-2016-10-31' Description: An AWS 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 指令。這些命令是對 AWS CLI的自訂命令。它們會包裝其他命令,將部署套件上傳至 Amazon S3,使用物件 URI 重寫範本,並更新函數的程式碼。

下面的範例指令碼會執行 Gradle 建置並上傳到它建立的部署套件。它在您第一次運行它時創建一個 AWS 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-java-events庫(3.0.0 及更新版本)。這些範例不需要 AWS SDK 作為相依性。

  • s3-java - 一種 Java 函數,它處理來自 Amazon S3 的通知事件,並使用 Java Class Library (JCL) 以從上傳的映像檔案建立縮圖。

  • 使用 API Gateway 調用 Lambda 函數 - 一個 Java 函數,其可掃描包含員工資訊的 Amazon DynamoDB 資料表。然後,其會使用 Amazon Simple Notification Service 向員工傳送文字訊息,慶祝他們的工作週年紀念日。此範例使用 API Gateway 叫用函數。