DynamoDB 错误处理 - Amazon DynamoDB

DynamoDB 错误处理

本节描述运行时错误,以及如何处理它们。它还描述特定于 Amazon DynamoDB 的错误消息和代码。

错误组成部分

程序发送请求后,DynamoDB 会尝试处理该请求。如果请求成功,DynamoDB 将返回一个 HTTP 成功状态代码 (200 OK),以及所请求操作的结果。

如果请求失败,DynamoDB 会返回一个错误。每个错误包含三个部分:

  • HTTP 状态代码(如 400)。

  • 异常名称(如 ResourceNotFoundException)。

  • 错误消息(如 Requested resource not found: Table: tablename not found)。

AWS SDK 负责将错误传播到应用程序,以便您能执行适当操作。例如,在 Java 程序中,您可以编写 try-catch 逻辑以处理 ResourceNotFoundException

如果您使用的不是 AWS SDK,将需要解析来自 DynamoDB 的低级响应内容。下面是一个此类响应的示例。

HTTP/1.1 400 Bad Request x-amzn-RequestId: LDM6CJP8RMQ1FHKSC1RBVJFPNVV4KQNSO5AEMF66Q9ASUAAJG Content-Type: application/x-amz-json-1.0 Content-Length: 240 Date: Thu, 15 Mar 2012 23:56:23 GMT {"__type":"com.amazonaws.dynamodb.v20120810#ResourceNotFoundException", "message":"Requested resource not found: Table: tablename not found"}

错误消息和代码

下面是 DynamoDB 返回的异常列表,按 HTTP 状态代码分组。如果确定重试?,则可以在此提交相同请求。如果确定重试?,则需要先解决客户端问题,然后再提交新请求。

HTTP 状态代码 400

HTTP 400 状态代码表示与请求相关的问题,例如身份验证失败、缺少必需的参数或者超出预置表吞吐量。必须先解决应用程序中存在的问题,然后再重新提交请求。

AccessDeniedException

消息:访问被拒绝。

客户端未正确签名请求。如果使用 AWS SDK,请求将自动为您签名;否则,请转到 AWS 一般参考签名版本 4 签名流程

确定重试? 否

ConditionalCheckFailedException

消息:有条件请求失败。

指定条件的计算结果为 false。例如,您可能已尝试对项目执行有条件更新,但属性的实际值与条件预期值不匹配。

确定重试? 否

IncompleteSignatureException

消息:请求签名不符合 AWS 标准

请求签名未包含所有必需的部分。如果使用 AWS SDK,请求将自动为您签名;否则,请转到AWS一般参考签名版本 4 签名流程

确定重试? 否

ItemCollectionSizeLimitExceededException

消息:超过集合大小。

对于包含全局二级索引的表,具有相同分区键值的项目组超过 10 GB 最大大小限制。有关项目集的更多信息,请参见 项目集合

确定重试? 是

LimitExceededException

消息:指定订阅者的操作过多。

并发控制层面操作过多。处于 CREATINGDELETINGUPDATING 状态的表和索引的累计数量不能超过 50。

确定重试? 是

MissingAuthenticationTokenException

消息:请求必须包含有效(已注册)的 AWS 访问密钥 ID。

请求未包含所需的授权标头,或请求的格式不正确。请参阅 DynamoDB 低级 API

确定重试? 否

ProvisionedThroughputExceededException

消息:已超过表或一个或更多全局二级索引的最大允许预置吞吐量。要查看预置吞吐量与占用吞吐量的性能指标,请打开 Amazon CloudWatch 控制台

示例:您的请求速率过高。DynamoDB 的 AWS SDK 自动重试收到此异常的请求。除非重试队列太长以致无法完成,否则请求最终都会成功。请使用错误重试和指数回退降低请求频率,

确定重试? 是

RequestLimitExceeded

消息:吞吐量超出您的账户的当前吞吐量限制。要请求提高限制,请联系 AWS Support:https://aws.amazon.com/support

示例:按需请求的速率超出允许的账户吞吐量。

确定重试? 是

ResourceInUseException

消息:您尝试更改的资源正在使用中。

示例:您尝试重新创建现有表,或删除目前处于 CREATING 状态的表。

确定重试? 否

ResourceNotFoundException

消息:未找到请求的资源。

示例:您正在请求的表不存在,或过早进入 CREATING 状态。

确定重试? 否

ThrottlingException

消息:请求速率超出允许吞吐量。

此异常将作为 AmazonServiceException 响应返回,并带有 THROTTLING_EXCEPTION 状态代码。如果过快执行控制层面 API 操作,则可能会返回此异常。

对于使用按需模式的表,如果请求速率过高,则可能会针对任何数据层面 API 操作返回此异常。要了解有关按需扩展的更多信息,请参见峰值流量和扩展属性

确定重试? 是

UnrecognizedClientException

消息:访问密钥 ID 或安全令牌无效。

请求签名错误。最有可能的原因是 AWS 访问密钥 ID 或密钥无效。

确定重试? 是

ValidationException

消息:根据遇到的特定错误而变化

有多种原因可能导致此错误,例如缺少必需参数,值超出范围,或者数据类型不匹配。错误消息包含有关导致错误的请求特定部分的详细信息。

确定重试? 否

HTTP 状态代码 5xx

HTTP 5xx 状态代码表示必须由 AWS 解决的问题。这可能是临时错误,在这种情况下,可以重试请求直到成功。否则,请转至 AWS Service Health Dashboard,查看是否存在与服务相关的任何操作问题。

Internal Server Error (HTTP 500)

DynamoDB 无法处理您的请求。

确定重试? 是

注意

处理项目时可能遇到内部服务器错误。这些是表的生命周期中的预期错误。可立即重试所有失败的请求。

当您收到写入操作的状态代码 500 时,该操作可能已成功或失败。如果写入操作是 TransactWriteItem 请求,那么可以重试该操作。如果写入操作是单项写入请求,例如 PutItemUpdateItemDeleteItem,那么您应用程序应该在重试操作之前读取项目的状态,和/或使用 条件表达式 以确保项目在重试后保持正确的状态,无论之前的操作是成功还是失败。如果写入操作要求幂等性,请使用 TransactWriteItem,它通过自动指定 ClientRequestToken 消除多次尝试执行同一操作的歧义,从而支持幂等性请求。

Service Unavailable (HTTP 503)

DynamoDB 当前不可用。(这应是一种暂时状态。)

确定重试? 是

应用程序中的错误处理

为了让应用程序平稳运行,需要添加逻辑以抓取和响应错误。典型的方法包括使用 try-catch 块或 if-then 语句。

AWS SDK 执行自己的重试和检查错误。如果使用某个 AWS SDK 时遇到错误,错误代码和错误描述可帮助您纠正错误。

您还应该会在响应中看到 Request ID。如果需要使用 Request ID 支持诊断问题,则 AWS 会很有用。

下面的 Java 代码示例尝试从 DynamoDB 表中获取项目并执行基本错误处理。(在此情况下,它仅向用户告知请求失败。)

Table table = dynamoDB.getTable("Movies"); try { Item item = table.getItem("year", 1978, "title", "Superman"); if (item != null) { System.out.println("Result: " + item); } else { //No such item exists in the table System.out.println("Item not found"); } } catch (AmazonServiceException ase) { System.err.println("Could not complete operation"); System.err.println("Error Message: " + ase.getMessage()); System.err.println("HTTP Status: " + ase.getStatusCode()); System.err.println("AWS Error Code: " + ase.getErrorCode()); System.err.println("Error Type: " + ase.getErrorType()); System.err.println("Request ID: " + ase.getRequestId()); } catch (AmazonClientException ace) { System.err.println("Internal error occurred communicating with DynamoDB"); System.out.println("Error Message: " + ace.getMessage()); }

在此代码示例中,try-catch 结构处理两种不同的异常:

  • AmazonServiceException—客户端请求正确地传输到 DynamoDB,但 DynamoDB 无法处理请求并返回错误响应时引发。

  • AmazonClientException—客户端无法从服务获得响应或者客户端无法解析来自服务的响应时引发。

错误重试和指数回退

网络上的大量组件(例如 DNS 服务器、交换机、负载均衡器等)都可能在某个指定请求生命周期中的任一环节出现问题。在联网环境中,处理这些错误响应的常规技术是在客户应用程序中实施重试。此方法提高应用程序的可靠性。

每个 AWS SDK 都会自动实现重试逻辑。可以修改重试参数以满足您的需求。例如,考虑一个需要 fail-fast 策略的 Java 应用程序,并且在出错时不允许重试。利用 AWS SDK for Java,您可以使用 ClientConfiguration 类并提供值为 maxErrorRetry0 来禁用重试。有关更多信息,请参阅适用于您编程语言的 AWS SDK 文档。

如果您没有使用 AWS SDK,则应当对收到服务器错误 (5xx) 的原始请求执行重试。但是,客户端错误(4xx,不是 ThrottlingExceptionProvisionedThroughputExceededException)表示您需要对请求本身进行修改,先修正了错误然后再重试。

除了简单重试之外,每个 AWS SDK 还实施指数回退算法来实现更好的流程控制。指数回退的原理是对于连续错误响应,重试等待间隔越来越长。例如,第一次重试最多等待 50 毫秒,第二次重试最多等待 100 毫秒,第三次重试最多等待 200 毫秒,依此类推。但是,如果过段时间后,请求仍然失败,则出错的原因可能是因为请求大小超出预置吞吐量,而不是请求速率的问题。您可以设置最大重试次数,在大约一分钟的时候停止重试。如果请求失败,请检查您的预置吞吐量选项。

注意

AWS SDK 实施自动重试逻辑和指数回退。

大多数指数回退算法会利用抖动(随机延迟)防止连续的冲突。由于在这些情况下不会尝试避免此类冲突,因此无需使用此随机数字。但是,如果使用并发客户端,抖动可帮助您更快地成功执行请求。有关更多信息,请参见有关指数回退和抖动的博文。

批量操作和错误处理

DynamoDB 低级 API 支持批量读取和写入操作。BatchGetItem 从一个或多个表中读取项目,BatchWriteItem 在一个或多个表中放置或删除项目。这些批量操作作为其他非批量 DynamoDB 操作的包装得以实现。换句话说,BatchGetItem 为批处理中的每个项目调用 GetItem 一次。同样,BatchWriteItem 根据需要为批处理中的每个项目调用 DeleteItemPutItem

批量操作可以容忍批处理中的个别请求失败。例如,假设一个 BatchGetItem 请求读取五个项目。即使某些底层 GetItem 请求失败,这也不会导致整个 BatchGetItem 操作失败。但是,如果所有五个读取操作都失败,则整个 BatchGetItem 失败。

批量操作会返回有关各失败请求的信息,以便您诊断问题并重试操作。对于 BatchGetItem,在响应的 UnprocessedKeys 值中会返回有问题的表和主键。对于 BatchWriteItem,在 UnprocessedItems 中返回类似信息。

造成读取失败或写入失败的最可能原因是限制。对于 BatchGetItem,原因是批量请求中的一个或多个表没有足够的预置读取容量来支持操作。对于 BatchWriteItem,原因是一个或多个表没有足够的预置写入容量。

如果 DynamoDB 返回了任何未处理的项目,应对这些项目重试批量操作。然而,我们强烈建议您使用指数回退算法。如果立即重试批量操作,底层读取或写入请求仍然会由于各表的限制而失败。如果使用指数回退延迟批量操作,批处理中的各请求成功的可能性更大。