Java 中的 AWS Lambda 函数错误 - AWS Lambda
AWS 文档中描述的 AWS 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅中国的 AWS 服务入门

Java 中的 AWS Lambda 函数错误

当您的函数引发错误时,Lambda 将有关此错误的详细信息返回给调用者。Lambda 返回的响应的正文包含一个 JSON 文档,其中包含错误名称、错误类型和堆栈帧数组。调用该函数的客户端或服务可以处理错误或将其一直传递到最终用户。您可以使用自定义例外向用户返回客户端错误的有用信息。

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 an array 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 contain 2 numbers.", "errorType":"java.lang.InputLengthException", "stackTrace": [ "example.HandlerDivide.handleRequest(HandlerDivide.java:23)", "example.HandlerDivide.handleRequest(HandlerDivide.java:14)" ] }

在此示例中,InputLengthExceptionRuntimeExceptionRequestHandler 接口不允许检查到的异常。RequestStreamHandler 接口支持引发 IOException 错误。

前一个示例中的返回语句也可能引发运行时异常。

return numerator/denominator;

此代码可以返回算术错误。

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

查看错误输出

您可以在 Lambda 控制台、命令行或 AWS 开发工具包中使用测试负载调用您的函数和查看错误输出。错误输出也会捕获到函数的执行日志中,当启用跟踪 时,会捕获到 AWS X-Ray 中。

要在 Lambda 控制台中查看错误输出,请使用测试事件调用它。

在 Lambda 控制台中调用函数

  1. 打开 Lambda 控制台 函数页面

  2. 选择函数。

  3. Test (测试) 按钮旁的下拉菜单中,选择 Configure test events (配置测试事件)

    
            在 Lambda 控制台中配置测试事件。
  4. 选择与函数处理的事件匹配的 Event template (事件模板)

  5. 输入测试事件的名称并根据需要修改事件结构。

  6. 选择 Create

  7. 选择 Test

Lambda 控制台同步调用您的函数并显示结果。要查看响应、日志和其他信息,请展开 Details (详细信息) 部分。

在您从命令行调用函数时,AWS CLI 将响应拆分为两个文档。为指示出现函数错误,在终端中显示的响应包含 FunctionError 字段。函数返回的响应或错误写入到输出文件。

$ aws lambda invoke --function-name my-function out.json { "StatusCode": 200, "FunctionError": "Unhandled", "ExecutedVersion": "$LATEST" }

查看输出文件以查看错误文档。

$ cat out.json {"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。要在从命令行调用函数时查看日志,请使用 --log-type 选项并解码响应中的 base64 字符串。

$ aws lambda invoke --function-name my-function --payload "[100,0]" out.json --log-type Tail \ --query 'LogResult' --output text | base64 -d START RequestId: 081f7522-xmpl-48e2-8f67-96686904bb4f Version: $LATEST EVENT: [ 100, 0 ]EVENT TYPE: class java.util.ArrayList/ by zero: java.lang.ArithmeticException java.lang.ArithmeticException: / by zero at example.HandlerDivide.handleRequest(HandlerDivide.java:28) at example.HandlerDivide.handleRequest(HandlerDivide.java:13) END RequestId: 081f7522-xmpl-48e2-8f67-96686904bb4f REPORT RequestId: 081f7522-xmpl-48e2-8f67-96686904bb4f Duration: 4.20 ms Billed Duration: 100 ms Memory Size: 512 MB Max Memory Used: 95 MB XRAY TraceId: 1-5e73162b-1919xmpl2592f4549e1c39be SegmentId: 3dadxmpl48126cb8 Sampled: true

有关日志的更多信息,请参阅Java 中的 AWS Lambda 函数日志记录

了解错误类型和来源

当您调用函数时,多个子系统会处理请求、事件、输出和响应。错误可能来自 Lambda 服务(调用错误)或函数的实例。函数错误包括处理程序代码返回的异常和 Lambda 运行时返回的异常。

Lambda 服务接收调用请求并对其进行验证。它检查权限,验证事件文档是否为有效的 JSON 文档,并检查参数值。如果 Lambda 服务遇到错误,它会返回指示错误原因的异常类型、消息和 HTTP 状态代码。

注意

有关 Invoke API 操作可能返回的错误的完整列表,请参阅 Lambda API 参考中的调用错误

来自 Lambda 服务的 4xx 系列错误表示调用者可以通过修改请求、请求权限或重试来修复的错误。5xx 系列错误表示 Lambda 服务存在问题,或者函数的配置或资源存在问题。调用方无法解决这些问题,但函数的所有者可能能够修复它们。

如果请求通过验证,Lambda 将其发送到函数的实例。运行时将事件文档转换为一个对象,并将该对象传递给处理程序代码。在此过程中可能会发生错误,例如,如果处理程序方法的名称与函数的配置不匹配,或者如果调用在处理程序代码返回响应之前发生超时。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 服务不返回错误代码。2xx 系列状态代码表示 Lambda 服务接受了请求。Lambda 通过在响应中包含 X-Amz-Function-Error 标头(而不是错误代码)来指示错误。

对于异步调用,事件在 Lambda 将它们发送到函数之前排队。对于有效的请求,Lambda 立即返回成功响应并将事件添加到队列中。然后,Lambda 从队列中读取事件并调用该函数。如果发生错误,则 Lambda 会重试行为,而行为根据错误类型而异。有关更多信息,请参阅异步调用

客户端中的错误处理

调用 Lambda 函数的客户端可以选择处理错误或将错误传递给最终用户。正确的错误处理行为取决于应用程序的类型、受众以及错误来源。例如,如果调用失败且出现错误代码 429(请求太多),AWS CLI 会重试最多 4 次,然后向用户显示错误。

$ aws lambda invoke --function-name my-function out.json An error occurred (TooManyRequestsException) when calling the Invoke operation (reached max retries: 4): Rate Exceeded.

对于其他调用错误,正确的行为取决于响应代码。5xx 系列错误可能表示用户无需采取任何操作即可解决的临时状况。重试可能会成功,也可能会不成功。4xx 系列错误(而不是 429)通常表示请求发生错误。重试不可能成功。

对于函数错误,客户端可以处理错误文档并以用户友好的格式显示错误消息。基于浏览器的应用程序可能会显示错误消息和类型,但忽略堆栈跟踪。AWS CLI 将错误对象保存到输出文件中,而显示从响应标头生成的文档。

$ aws lambda invoke --function-name my-function --payload '[1000]' out.json { "StatusCode": 200, "FunctionError": "Unhandled", "ExecutedVersion": "$LATEST" }

例 out.json

{"errorMessage":"Input must be an array that contains 2 numbers.","errorType":"example.InputLengthException","stackTrace":["example.HandlerDivide.handleRequest(HandlerDivide.java:22)","example.HandlerDivide.handleRequest(HandlerDivide.java:13)"]}

其他 AWS 服务中的错误处理

当 AWS 服务调用您的函数时,服务会选择调用类型和重试行为。AWS 服务可以按计划调用您的函数,以响应资源上的生命周期事件或者针对来自用户的请求提供响应。某些服务异步调用函数并让 Lambda 处理错误,而其他服务则重试或将错误传回给用户。

例如,API 网关 将所有调用和函数错误视为内部错误。如果 Lambda API 拒绝调用请求,则 API 网关 返回 500 错误代码。如果函数运行但返回错误,或返回格式错误的响应,则 API 网关 返回 502 错误代码。要自定义错误响应,您必须捕获代码中的错误并以所需格式设置响应的格式。

要确定错误来源及其原因,请使用 AWS X-Ray。使用 X-Ray,您可以找出哪些组件遇到错误,并查看有关异常的详细信息。以下示例显示导致来自 API 网关 的 502 响应的函数错误。


        使用 API 网关 跟踪函数错误的映射。

通过对您的函数启用主动跟踪,开始使用 X-Ray。

有关其他服务处理程序错误的详细信息,请参阅将 AWS Lambda 与其他服务一起使用章节中的主题。

示例应用程序中的错误处理

本指南的 GitHub 存储库包括演示错误使用情况的示例应用程序。每个示例应用程序都包含用于轻松部署和清理的脚本、一个 AWS 无服务器应用程序模型 (AWS SAM) 模板和支持资源。

Java 中的示例 Lambda 应用程序

  • blank-java – 一个 Java 函数,用于显示 Lambda 的 Java 库、日志记录、环境变量、层、AWS X-Ray 跟踪、单元测试和 AWS 开发工具包的使用情况。

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

  • java-events – 一个最小的 Java 函数,它将 aws-lambda-java-events 库与不需要 AWS 开发工具包作为依赖项的事件类型(例如 Amazon API Gateway)结合使用。

  • java-events-v1sdk – 一个 Java 函数,它将 aws-lambda-java-events 库与需要 AWS 开发工具包作为依赖项的事件类型(Amazon Simple Storage Service、Amazon DynamoDB 和 Amazon Kinesis)结合使用。

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

java-basic 函数包括返回自定义运行时异常的处理程序 (HandlerDivide)。HandlerStream 处理程序实现 RequestStreamHandler 并可能引发 IOException 检查的异常。