Java 中的 AWS Lambda 函數錯誤 - AWS Lambda

Java 中的 AWS Lambda 函數錯誤

您的程式碼若引發錯誤,Lambda 將產生該項錯誤的 JSON 表示法。此錯誤文件會顯示在叫用記錄中,同步叫用的情況下還會顯示在輸出中。

此頁面說明如何使用 Lambda 主控台和 AWS CLI 來檢視 Java 執行時間的 Lambda 函數叫用錯誤。

語法

在下列範例中,執行階段無法將事件還原序列化為物件。輸入是一個有效的 JSON 類型,但它與處理常式方法預期的類型不相符。

範例 Lambda 執行時間錯誤

{ "errorMessage": "An error occurred during JSON parsing", "errorType": "java.lang.RuntimeException", "stackTrace": [], "cause": { "errorMessage": "com.fasterxml.jackson.databind.exc.InvalidFormatException: Can not construct instance of java.lang.Integer from String value '1000,10': not a valid Integer value\n at [Source: lambdainternal.util.NativeMemoryAsInputStream@35fc6dc4; line: 1, column: 1] (through reference chain: java.lang.Object[0])", "errorType": "java.io.UncheckedIOException", "stackTrace": [], "cause": { "errorMessage": "Can not construct instance of java.lang.Integer from String value '1000,10': not a valid Integer value\n at [Source: lambdainternal.util.NativeMemoryAsInputStream@35fc6dc4; line: 1, column: 1] (through reference chain: java.lang.Object[0])", "errorType": "com.fasterxml.jackson.databind.exc.InvalidFormatException", "stackTrace": [ "com.fasterxml.jackson.databind.exc.InvalidFormatException.from(InvalidFormatException.java:55)", "com.fasterxml.jackson.databind.DeserializationContext.weirdStringException(DeserializationContext.java:907)", ... ] } } }

運作方式

當您叫用 Lambda 函數時,Lambda 會接收叫用請求,驗證執行角色中的許可,確認事件文件是否為有效的 JSON 文件,以及檢查參數值。

如果請求通過驗證,Lambda 會將請求傳送至函數執行個體。Lambda 執行時間環境會將事件文件轉換為物件,並將它傳遞至您的函數處理常式。

如果 Lambda 發生錯誤,它會傳回例外狀況類型、訊息,以及指出錯誤原因的 HTTP 狀態碼。叫用 Lambda 函數的用戶端或服務能以程式設計方式來處理錯誤或將其傳遞給最終使用者。正確的錯誤處理行為取決於應用程式類型、對象和錯誤的來源而定。

下列清單說明您可以從 Lambda 中接收的狀態碼範圍。

2xx

回應中含有 X-Amz-Function-Error 標頭的 2xx 序列錯誤表示 Lambda 執行時間或函數錯誤。2xx 序列狀態碼表示 Lambda 接受請求,而非錯誤代碼,Lambda 透過在回應中包含 X-Amz-Function-Error 標頭來指示錯誤。

4xx

4xx 序列錯誤表示叫用用戶端或服務可藉由修改請求、請求許可或重試請求來進行修正的錯誤。除 429 以外的 4xx 序列錯誤則表示請求錯誤。

5xx

5xx 序列錯誤表示 Lambda 存在問題,或函數的組態或資源存在問題。5xx 序列錯誤則可表示暫時狀況,使用者無需任何動作即可解決。叫用用戶端或服務無法解決這些問題,但 Lambda 函數的擁有者可能可以修正該問題。

如需叫用錯誤的完整清單,請參閱 InvokeFunction 錯誤

建立傳回例外狀況的函數

您可以建立 Lambda 函數,以向使用者顯示人類可讀取的錯誤訊息。

注意

若要測試此程式碼,您需要將 InputLengthException.java 納入專案 src 資料夾。

範例 src/main/java/example/HandlerDivide.java - 執行時間例外狀況

import java.util.List; // Handler value: example.HandlerDivide public class HandlerDivide implements RequestHandler<List<Integer>, Integer>{ Gson gson = new GsonBuilder().setPrettyPrinting().create(); @Override public Integer handleRequest(List<Integer> event, Context context) { LambdaLogger logger = context.getLogger(); // process event if ( event.size() != 2 ) { throw new InputLengthException("Input must be a list that contains 2 numbers."); } int numerator = event.get(0); int denominator = event.get(1); logger.log("EVENT: " + gson.toJson(event)); logger.log("EVENT TYPE: " + event.getClass().toString()); return numerator/denominator; } }

當函數擲回 InputLengthException,Java 執行階段會將其序列化到下列文件。

範例 錯誤文件 (已新增空格)

{ "errorMessage":"Input must be a list that contains 2 numbers.", "errorType":"java.lang.InputLengthException", "stackTrace": [ "example.HandlerDivide.handleRequest(HandlerDivide.java:23)", "example.HandlerDivide.handleRequest(HandlerDivide.java:14)" ] }

在這個例子中,InputLengthException 是一個 RuntimeExceptionRequestHandler 介面不允許已檢查的例外狀況。該 RequestStreamHandler 介面支援擲回 IOException 錯誤。

上例中的 return 陳述式也可以擲回執行階段例外狀況。

return numerator/denominator;

此代碼會傳回一個算術錯誤。

{"errorMessage":"/ by zero","errorType":"java.lang.ArithmeticException","stackTrace":["example.HandlerDivide.handleRequest(HandlerDivide.java:28)","example.HandlerDivide.handleRequest(HandlerDivide.java:13)"]}

使用 Lambda 主控台

您可以透過設定測試事件和檢視輸出,來叫用 Lambda 主控台上的函數。系統會在函數的執行日誌中擷取錯誤輸出,以及在 AWS X-Ray 中啟用主動追蹤時加以擷取。

若要在 Lambda 主控台中叫用函數

  1. 開啟 Lambda 主控台中的 Functions (函數) 頁面

  2. 選擇要測試的函數,並選擇 Test (測試)。

  3. Test event (測試事件) 下方,選取 New event (新事件)。

  4. 選取 Template (範本)。

  5. 對於 Name (名稱),輸入測試的名稱。在文字輸入方塊中,輸入 JSON 測試事件。

  6. 選擇 Save changes (儲存變更)。

  7. 選擇 Test (測試)。

Lambda 主控台會同步叫用您的函數並顯示結果。若要查看回應、日誌和其他資訊,請展開 Details (詳細資料) 區段。

使用 AWS Command Line Interface​ (AWS CLI​)

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

當您在 AWS CLI 中叫用 Lambda 函數時,AWS CLI 會將回應分割成兩個文件。AWS CLI 回應會顯示在命令提示中。如果發生錯誤,則回應會包含 FunctionError 欄位。該函式傳回的叫用回應或錯誤會寫入至輸出檔案。例如,output.jsonoutput.txt

下列叫用命令範例示範了如何叫用函數,並將叫用回應寫入 output.txt 檔案。

aws lambda invoke \ --function-name my-function \ --cli-binary-format raw-in-base64-out \ --payload '{"key1": "value1", "key2": "value2", "key3": "value3"}' output.txt

如果您使用 AWS CLI 第 2 版,則需要 cli-binary-format 選項。若要讓此成為預設的設定,請執行 aws configure set cli-binary-format raw-in-base64-out。如需詳細資訊,請參閱《支援 AWS CLI 的全域命令列選項》。

您應在命令提示中看到 AWS CLI 回應:

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

您應在 output.txt 檔案中看到函數叫用回應。在相同的命令提示下,您還可以使用下列命令提示來檢視輸出:

cat output.txt

您應在命令提示下看到叫用回應。

{"errorMessage":"Input must contain 2 numbers.","errorType":"java.lang.InputLengthException","stackTrace": ["example.HandlerDivide.handleRequest(HandlerDivide.java:23)","example.HandlerDivide.handleRequest(HandlerDivide.java:14)"]}

Lambda 也會在函數日誌中記錄高達 256 KB 的錯誤物件。如需詳細資訊,請參閱 Java 中的 AWS Lambda 函數記錄

其他 AWS 服務中的錯誤處理

當另一項 AWS 服務叫用您的函數時,服務會選擇叫用類型和重試行為。AWS 服務可以按照排程叫用您的函數、回應資源上的生命週期事件,或為使用者的請求服務。某些服務會以非同步方式呼叫函數,並讓 Lambda 處理錯誤,而其他服務則會重試或將錯誤傳回給使用者。

例如,API Gateway 會將所有呼叫和函數錯誤視為內部錯誤。如果 Lambda API 拒絕叫用請求,則 API Gateway 會傳回 500 錯誤代碼。如果函數執行但傳回錯誤,或傳回格式錯誤的回應,API Gateway 會傳回錯誤代碼 502。若要自訂錯誤回應,您必須在程式碼中發現錯誤,並以必要的格式格式化回應。

我們建議使用 AWS X-Ray 來判斷錯誤的來源及其原因。X-Ray 可讓您找出哪個元件遇到錯誤,並查看錯誤的詳細資訊。下列範例顯示來自 API Gateway 的 502 回應中導致的函數錯誤。


          透過 API Gateway 處理函數錯誤的流程圖。

如需詳細資訊,請參閱 在 AWS Lambda 中檢測 Java 程式碼

範例應用程式

本指南的 GitHub 儲存庫包含示範錯誤使用方式的範例應用程式。每個範例應用程式都包含可輕鬆部署和清理的指令碼、AWS Serverless Application Model (AWS SAM) 範本和支援資源。

以 Java 編寫的範例 Lambda 應用程式

  • blank-java - 一種 Java 函數,它示範如何使用 Lambda 的 Java 程式庫、記錄、環境變數、層、AWS X-Ray 追蹤、單元測試和 AWS 開發套件。

  • java-basic - 具有單元測試和變數日誌記錄組態的最小 Java 函數。

  • java-events - 使用 aws-lambda-java-events 程式庫最新版本 (3.0.0 及更新版本) 的最小 Java 函數。這些範例不需要 AWS 開發套件做為相依項目。

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

java-basic 函數包含傳回自訂執行階段例外狀況的處理常式 (HandlerDivide)。HandlerStream 處理常式會實作 RequestStreamHandler 並會擲回一個 IOException 已檢查的例外狀況。

後續步驟?