Amazon Kinesis Data Streams
开发人员指南
AWS 文档中描述的 AWS 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 Amazon AWS 入门

Amazon Kinesis Data Streams 使用者问题排查

在使用 Kinesis 客户端库时跳过了某些 Kinesis Data Streams 记录

跳过记录的最常见原因是未处理从 processRecords 引发的异常。Kinesis Client Library (KCL) 依靠您的 processRecords 代码来处理在处理数据记录时引发的任何异常。processRecords 引发的任何异常都会被 KCL 吸收。为避免因为反复出现的故障无休止地进行重试,KCL 不会重新发送在发生异常时处理的那批记录。然后,KCL 会在不重新启动记录处理器的情况下对下一批数据记录调用 processRecords。这有效地导致使用者应用程序观察到跳过的记录。要防止跳过记录,请适当处理 processRecords 中的所有异常。

属于同一分片的记录通过不同的记录处理器同时处理

对于任何正在运行的 Kinesis Client Library (KCL) 应用程序,一个分片只有一个所有者。但是,多个记录处理器可以临时处理同一分片。在工作程序实例丢失网络连接的情况下,KCL 会假定此无法联系的工作程序不再处理记录,并会在故障转移时间到期后指示其他工作程序来接管其工作。在一段很短的时间内,新的记录处理器和来自无法联系的工作程序的记录处理器可能都会处理来自同一个分片的数据。

您应该根据您的应用程序设置适当的故障转移时间。对于低延迟应用程序,默认值 10 秒可以代表您可以等待的最长时间。但是,在一些情况下,如您预计会有一些连接问题(如跨地理区域打电话)并且连接可能较频繁地中断时,这个数字设置可能就过低了。

您的应用程序应预料到并处理这种情况,尤其是因为网络连接通常会恢复到之前无法访问的工作程序。如果一个记录处理器让另一个记录处理器接手其分片,它必须处理以下两种情况才能顺利执行关闭:

  1. processRecords 的当前调用完成后,KCL 会对记录处理器调用 shutdown 方法,并说明关闭原因为“ZOMBIE”。 您的记录处理器应视情况清除所有资源然后退出。

  2. 如果您尝试对“zombie”工作程序执行检查点操作,KCL 会引发 ShutdownException。收到此异常后,您的代码应完全退出当前方法。

有关更多信息,请参阅 处理重复记录

使用者应用程序的读取速率比预期的慢

读取吞吐量低于预期的最常见原因如下:

  1. 多个使用者应用程序的总读取量超过每个分片的限制。有关更多信息,请参阅 Amazon Kinesis Data Streams 限制。在这种情况下,请增加 Kinesis data stream 中的分片数。

  2. 指定每个调用的最大 GetRecords 数的 limit 可能已配置为较低的值。如果您正在使用 KCL,您可能已经使用一个较低的 maxRecords 属性值配置了工作程序。一般来说,我们推荐对此属性使用系统默认值。

  3. 出于很多可能的原因,您的 processRecords 调用内的逻辑花费的时间可能超过预期;该逻辑可能是 CPU 使用率高、I/O 阻止或同步出现瓶颈。要测试是否如此,请对空的记录处理器进行测试运行并比较读取吞吐量。有关如何跟踪传入数据的信息,请参阅重新分片、扩展和并行处理

如果您只有一个使用者应用程序,那么读取速率比放入速率至少高两倍始终是可能的。这是因为您可以写入最多 每秒 1000 条记录 可用于写入,最多可达的最大总数据写入速率为 每秒 1 MB (包括分区键)。每个打开的分片可支持最多 每秒 5 次交易 可用于读取,最多可达的最大总数据读取速率为 每秒 2 MB。请注意,每次读取(GetRecords 调用)都将获取一批记录。GetRecords 返回的数据的大小因分片使用率不同而异。GetRecords 可返回的数据的最大大小为 10 MB。如果某个调用返回了该限制,在接下来 5 分钟内进行的后续调用将引发 ProvisionedThroughputExceededException

即使流中有数据,GetRecords 仍然返回空记录阵列

使用或获取记录是一种拉取模型。开发人员应该在不会回退的连续循环中调用 GetRecords。每个 GetRecords 调用还将返回一个 ShardIterator 值,该值必须在循环的下一个迭代中使用。

GetRecords 操作不会卡住。相反,它将立即返回一些相关数据记录或一个空的 Records 元素。在两种情况下,将返回空的 Records 元素:

  1. 目前分片中没有更多数据.

  2. ShardIterator 指向的分片部分附近没有数据。

后一种情况很微妙,但却是避免在检索数据时搜寻时间无止境(延迟)的一种必要的设计折衷。因此,使用流的应用程序应循环调用 GetRecords,当然同时也要处理空记录。

在生产场景中,仅当 NextShardIterator 值为 NULL 时,才应退出连续循环。当 NextShardIteratorNULL 时,这意味着当前分片已关闭,ShardIterator 值的指向应越过最后一条记录。如果使用者应用程序从不调用 SplitShardMergeShards,则分片会保持打开状态,且调用 GetRecords 后绝不会返回值为 NULLNextShardIterator

如果您使用 Kinesis Client Library (KCL),则会自动为您抽取以上使用模式。这包括自动处理一组动态变化的分片。在 KCL 中,开发人员只需提供处理传入记录的逻辑。因为该库会为您连续调用 GetRecords,所以这是可以实现的。

分片迭代器意外过期

每个 GetRecords 请求(NextShardIterator 的形式)都会返回一个新的分片迭代器,然后您可在下一个 GetRecords 请求(ShardIterator 的形式)中使用该迭代器。此分片迭代器一般来说不会在您使用前过期。不过,您可能会发现,由于您超过 5 分钟没有调用 GetRecords,或者您重新启动使用者应用程序,该分片迭代器将会过期。

如果分片迭代器在您还没能使用之前很快过期,这可能表示 Kinesis 使用的 DynamoDB 表没有足够的容量存储租赁数据。如果您的分片数量很多,则很可能发生这种情况。要解决此问题,请增加分配给分片表的写入容量。有关更多信息,请参阅 跟踪 Amazon Kinesis Data Streams Application状态

使用者记录处理滞后

对于大多数使用案例,使用者应用程序从流中读取最新数据。在特定情况下,使用者读取可能会滞后,而您可能并不希望出现这种情况。在确定您的使用者读取滞后多久后,请查看使用者滞后的最常见原因。

GetRecords.IteratorAgeMilliseconds 指标开始,该指标跟踪流中所有分片和使用者的读取位置。请注意,如果某个迭代器的寿命超过了保留期的 50%(默认值为 24 小时,可配置为最高 7 天),则存在由于记录过期造成数据丢失的风险。一种快速的权宜之计是增加保留期。这会在您进一步对问题进行故障排除时防止重要数据丢失。有关更多信息,请参阅 利用 Amazon CloudWatch 监控 Amazon Kinesis Data Streams 服务。接下来,使用 Kinesis Client Library (KCL) 发出的自定义 CloudWatch 指标 MillisBehindLatest 来确定使用者应用程序从每个分片读取的滞后时间长度。有关更多信息,请参阅 利用 Amazon CloudWatch 监控 Kinesis 客户端库

下面是使用者滞后的最常见原因:

  • GetRecords.IteratorAgeMillisecondsMillisBehindLatest 突然发生大幅提升,通常表明临时性问题,例如下游应用程序的 API 操作失败。如果任何一个指标持续指示此行为,您应该调查这些突然增长的原因。

  • 这些指标的逐步增大表明,由于处理记录的速度不够快,使用者无法与流保持同步。此行为最常见的根本原因是没有足够的物理资源,或者记录处理逻辑没有随着流吞吐量的增大而进行扩展。您可以查看 KCL 发出的与 processTask 操作关联的其他自定义 CloudWatch 指标,包括 RecordProcessor.processRecords.TimeSuccessRecordsProcessed,从而验证此行为。

    • 如果您发现与吞吐量上升相关的 processRecords.Time 指标发生增长,则应该分析记录处理逻辑,以确定为什么逻辑没有随吞吐量的增长而扩展。

    • 如果您发现与吞吐量上升无关的 processRecords.Time 值发生增长,请检查您是否在关键路径中执行了任何阻塞性调用,这通常会导致记录处理速度下降。替代方法是通过增加分片数来提高并行度。最后,请确认需求高峰期间在底层处理节点上,您有足够数量的物理资源(内存、CPU 使用率等)。

未授权的 KMS 主密钥权限错误

当使用者应用程序从加密流读取但没有 KMS 主密钥的权限时,会发生此错误。要为应用程序分配权限以访问 KMS 密钥,请参阅在 AWS KMS 中使用密钥策略在 AWS KMS 中使用 IAM 策略