

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

# 疑難排解 Kinesis Data Streams 取用者
<a name="troubleshooting-consumers"></a>

**Topics**
+ [LeaseManagementConfig 建構函數的編譯錯誤](#compilation-error-leasemanagementconfig)
+ [使用 Kinesis 用戶端程式庫時，會略過部分 Kinesis Data Streams 記錄](#records-skipped)
+ [屬於相同碎片的記錄會同時由不同的記錄處理器處理](#records-belonging-to-the-same-shard)
+ [取用者應用程式讀取速度比預期慢](#consumer-app-reading-slower)
+ [即使串流中有資料，GetRecords 也會傳回空的記錄陣列](#getrecords-returns-empty)
+ [碎片疊代運算意外過期](#shard-iterator-expires-unexpectedly)
+ [消費者記錄處理落後](#record-processing-falls-behind)
+ [未經授權的 KMS 金鑰許可錯誤](#unauthorized-kms-consumer)
+ [DynamoDbException：更新表達式中提供的文件路徑無效，無法進行更新](#dynamo-db-exception)
+ [對消費者的其他常見問題進行故障診斷](#misc-troubleshooting-consumer)

## LeaseManagementConfig 建構函數的編譯錯誤
<a name="compilation-error-leasemanagementconfig"></a>

升級至 Kinesis Client Library (KCL) 3.x `LeaseManagementConfig` 版或更新版本時，您可能會遇到與建構函數相關的編譯錯誤。如果您要直接建立`LeaseManagementConfig`物件來設定組態，而不是`ConfigsBuilder`在 KCL 3.x 版或更新版本中使用 ，則在編譯 KCL 應用程式程式碼時可能會看到下列錯誤訊息。

```
Cannot resolve constructor 'LeaseManagementConfig(String, DynamoDbAsyncClient, KinesisAsyncClient, String)'
```

 3.x 版或更新版本的 KCL 需要您在 tableName 參數後面新增一個以上的參數 applicationName （類型：String)。
+ *之前*： leaseManagementConfig = new LeaseManagementConfig(tableName， dynamoDBClient， kinesisClient， streamName， workerIdentifier)
+ *After*： leaseManagementConfig = new LeaseManagementConfig(tableName， **applicationName**， dynamoDBClient， kinesisClient， streamName， workerIdentifier)

建議您使用 在 KCL 3.x 和更新版本中`ConfigsBuilder`設定組態，而不是直接建立 LeaseManagementConfig 物件。 `ConfigsBuilder` 提供更靈活且可維護的方式來設定 KCL 應用程式。

以下是使用 `ConfigsBuilder`設定 KCL 組態的範例。

```
ConfigsBuilder configsBuilder = new ConfigsBuilder(
    streamName,
    applicationName,
    kinesisClient,
    dynamoClient,
    cloudWatchClient,
    UUID.randomUUID().toString(),
    new SampleRecordProcessorFactory()
);

Scheduler scheduler = new Scheduler(
    configsBuilder.checkpointConfig(),
    configsBuilder.coordinatorConfig(),
    configsBuilder.leaseManagementConfig()
    .failoverTimeMillis(60000), // this is an example
    configsBuilder.lifecycleConfig(),
    configsBuilder.metricsConfig(),
    configsBuilder.processorConfig(),
    configsBuilder.retrievalConfig()
);
```

## 使用 Kinesis 用戶端程式庫時，會略過部分 Kinesis Data Streams 記錄
<a name="records-skipped"></a>

記錄遭略過最常見的原因是未處理由 `processRecords` 擲回的例外狀況。Kinesis Client Library (KCL) 倚賴 `processRecords` 程式碼以處理任何因處理資料記錄而引發的例外狀況。凡是 `processRecords` 擲回的任何例外狀況都將由 KCL 吸收。為避免因重複失敗造成無止盡重試，KCL 並不會重新傳送例外狀況發生時處理的該批次記錄。接著，KCL 將對下一批次的資料記錄呼叫 `processRecords` 而未重新啟動記錄處理器。這就導致了消費者應用程式察覺到記錄遭略過。為避免略過記錄，請由 `processRecords` 中妥善處理所有例外狀況。

## 屬於相同碎片的記錄會同時由不同的記錄處理器處理
<a name="records-belonging-to-the-same-shard"></a>

凡是任何執行中的 Kinesis Client Library (KCL) 應用程式，各碎片都只有一個擁有者。不過，多個記錄處理器可能暫時處理同一碎片。如果工作者執行個體失去網路連線，KCL 會假設無法連線的工作者在容錯移轉時間到期後不再處理記錄，並指示其他工作者執行個體接管。短暫期間內，新的記錄處理器和來自無法連線工作者的記錄處理器可能都會處理取自同一碎片的資料。

設定適合您應用程式的容錯移轉時間。對於低延遲應用程式，預設值 10 秒足可代表您希望等待的最長時間。但在部分情況下，如您預期會有連線問題，比方跨地理區域撥話而連線中斷可能會更頻繁，此數字設定或許就過低了。

您的應用程式應該預料到這種情況並予處理，特別是因為網路連線通常會恢復至先前無法連線的工作者。記錄處理器若由另一記錄處理器接管其碎片，則必須處理以下兩種情況才能順利執行關閉：

1. 目前對 的呼叫`processRecords`完成後，KCL 會叫用記錄處理器上的關閉方法，其關閉原因為「ZOMBIE」。您的記錄處理器應適當清理任何資源然後結束。

1.  當您嘗試對 'zombie' 工作者執行檢查點作業，KCL 會擲回 `ShutdownException`。收到此例外狀況後，您的程式碼應徹底結束目前方法。

如需詳細資訊，請參閱[處理重複的記錄](kinesis-record-processor-duplicates.md)。

## 取用者應用程式讀取速度比預期慢
<a name="consumer-app-reading-slower"></a>

讀取傳輸量低於預期最常見的原因如下：

1. 多個消費者應用程式的總讀取量超出每一碎片限制。如需詳細資訊，請參閱[配額和限制](service-sizes-and-limits.md)。在此情況下，增加 Kinesis 資料串流中的碎片數量。

1. 指定每次呼叫的 **GetRecords** 最大數目[限制](https://docs.aws.amazon.com/kinesis/latest/APIReference/API_GetRecords.html#API_GetRecords_RequestSyntax)可能設定了較低的值。如果您使用 KCL，則有可能是對工作者設定的 `maxRecords` 屬性值偏低。一般而言，建議您就此屬性使用系統預設值。

1. 出於諸多可能的原因，`processRecords` 呼叫內的邏輯所耗費的時間會比預期更久；該邏輯可能 CPU 使用率高、I/O 阻斷或同步存在瓶頸。若要測試是否如此，請對空的記錄處理器執行測試並比較讀取傳輸量。如需如何及時處理傳入資料的相關資訊，請參閱[使用重新分片、擴展和平行處理來變更碎片數量](kinesis-record-processor-scaling.md)。

如果您只有一個消費者應用程式，則讀取速率比放入速率至少高兩倍的情況絕對有可能。這是因為您每秒最多可寫入 1,000 筆記錄，最大總資料寫入速率為每秒 1 MB (包括分割區索引鍵)。每個開放碎片可支援最高每秒 5 筆交易的讀取數目，最大總資料讀取速率為每秒 2 MB。請注意，每次讀取 (**GetRecords** 呼叫) 都會取得一個批次的記錄。**GetRecords** 傳回的資料大小因碎片使用率而異。**GetRecords** 可傳回的資料大小上限為 10 MB。如果呼叫傳回該限制，則接下來 5 秒內發出的後續呼叫會擲回 `ProvisionedThroughputExceededException`。

## 即使串流中有資料，GetRecords 也會傳回空的記錄陣列
<a name="getrecords-returns-empty"></a>

取用 (取得) 記錄是屬於提取模型。開發人員應該在不含退避的連續迴圈中呼叫 [GetRecords](https://docs.aws.amazon.com/kinesis/latest/APIReference/API_GetRecords.html)。每次呼叫 **GetRecords** 還會傳回一個 `ShardIterator` 值，此值必須於下次重複迴圈時使用。

**GetRecords** 操作不會封鎖。而將立即傳回一些相關資料記錄或是空的 `Records` 元素。以下兩種情況會傳回空的 `Records` 元素：

1. 碎片中目前已無更多資料。

1. `ShardIterator` 所指向的碎片部分附近沒有資料。

後一種情況很微妙，但卻是避免在擷取記錄時搜尋時間 (延遲) 無止境的必要折衷設計。因此，取用串流的應用程式應循環呼叫 **GetRecords**，當然也要處理空記錄。

在生產情境下，僅當 `NextShardIterator` 值為 `NULL` 時才應結束連續迴圈。`NextShardIterator` 為 `NULL` 時，表示目前碎片已封閉，且 `ShardIterator` 值的指向處應會越過最後一筆記錄。如果取用端應用程式從未呼叫 **SplitShard** 或 **MergeShards**，則碎片將保持開放狀態，呼叫 **GetRecords** 就絕不會傳回 `NULL` 值的 `NextShardIterator`。

如果您使用 Kinesis Client Library (KCL)，則會為您抽象化上述消耗模式。這包括自動處理一組動態變化的碎片。使用 KCL 時，開發人員僅需提供處理傳入記錄的邏輯。能夠如此是因為程式庫會為您持續呼叫 **GetRecords**。

## 碎片疊代運算意外過期
<a name="shard-iterator-expires-unexpectedly"></a>

每次請求都將傳回新的碎片疊代運算 **GetRecords** (即 `NextShardIterator`)，供您用於下一次的 **GetRecords** 請求 (即 `ShardIterator`)。此碎片疊代運算在您使用之前一般不會過期。不過，您可能會發現，由於您超過 5 分鐘未呼叫 **GetRecords**，或者您重新啟動了消費者應用程式，碎片疊代運算即過期。

如果碎片疊代運算在您可以使用之前立即過期，這可能表示 Kinesis 使用的 DynamoDB 資料表沒有足夠的容量來存放租用資料。若您有大量的碎片，即很可能發生這種情況。要解決此問題，請增加對碎片資料表指派的寫入容量。如需詳細資訊，請參閱[使用租用資料表來追蹤 KCL 取用者應用程式處理的碎片](shared-throughput-kcl-consumers.md#shared-throughput-kcl-consumers-leasetable)。

## 消費者記錄處理落後
<a name="record-processing-falls-behind"></a>

對於大多數使用案例、消費者應用程式會從串流讀取最新的資料。特定情況下，消費者讀取可能落後，您應不希望出現這種情況。在查出消費者讀取落後多久之後，請查看導致消費者落後最常見的原因。

首先使用 `GetRecords.IteratorAgeMilliseconds` 指標，追蹤串流中所有碎片和消費者的讀取位置。請注意，如果疊代運算的存留期超過保留期間的 50% (預設為 24 小時，最多可設定為 365 天)，會有由於記錄過期而遺失資料的風險。快速的權宜之計是增加保留期間。這可使您在進一步對問題進行故障診斷時防止遺失重要資料。如需詳細資訊，請參閱[使用 Amazon CloudWatch 監控 Amazon Kinesis Data Streams 服務 Amazon CloudWatch](monitoring-with-cloudwatch.md)。接著，使用 Kinesis Client Library (KCL) `MillisBehindLatest` 發出的自訂 CloudWatch 指標 ，查出取用者應用程式從各碎片讀取落後多久的時間。如需詳細資訊，請參閱[使用 Amazon CloudWatch 監控 Kinesis 用戶端程式庫](monitoring-with-kcl.md)。

消費者可能落後最常見的原因如下：
+ `GetRecords.IteratorAgeMilliseconds` 或 `MillisBehindLatest` 突然大增通常表示暫時性的問題，例如對下游應用程式的 API 操作失敗。如果其中一個指標持續顯示此行為，則調查這些突然增加。
+ 上述指標若逐漸增加，表示消費者因處理記錄速度不夠快而未能與串流同步。此行為最常見的根本原因是實體資源不足，或者記錄處理邏輯沒有隨著串流傳輸量的增加而進行擴展。您可藉由查看 KCL 所發出與 `processTask` 操作相關聯的其他自訂 CloudWatch 指標，包括 `RecordProcessor.processRecords.Time`、`Success` 和 `RecordsProcessed` 以確認此行為。
  + 若您發現與傳輸量上升相關的 `processRecords.Time` 指標有所增加，即應分析您的記錄處理邏輯，以確定該邏輯為何沒有隨著傳輸量增加而擴展。
  + 若您發現與傳輸量上升無關的 `processRecords.Time` 值有所增加，請檢查您是否在重要路徑上執行了任何封鎖呼叫，這通常會導致記錄處理速度下降。替代方法是增加碎片數目以提高並行處理程度。最後，請確認您在尖峰需求期間基礎處理節點上有足夠數量的實體資源 （記憶體、CPU 使用率等）。

## 未經授權的 KMS 金鑰許可錯誤
<a name="unauthorized-kms-consumer"></a>

當取用者應用程式在沒有 AWS KMS 金鑰許可的情況下從加密串流讀取時，會發生此錯誤。若要為應用程式指派許可使其能夠存取 KMS 金鑰，請參閱[在 AWS KMS 中使用金鑰政策](https://docs.aws.amazon.com/kms/latest/developerguide/key-policies.html)及[搭配 AWS KMS 使用 IAM 政策](https://docs.aws.amazon.com/kms/latest/developerguide/iam-policies.html)。

## DynamoDbException：更新表達式中提供的文件路徑無效，無法進行更新
<a name="dynamo-db-exception"></a>

搭配 2.27.19 到 2.27.23 適用於 Java 的 AWS SDK 版本使用 KCL 3.x 時，您可能會遇到下列 DynamoDB 例外狀況：

 「software.amazon.awssdk.services.dynamodb.model.DynamoDbException：更新表達式中提供的文件路徑不適用於更新 （服務：DynamoDb，狀態碼：400，請求 ID：xxx)」

由於 中的已知問題會影響 KCL 3.x 管理的 DynamoDB 中繼資料表 適用於 Java 的 AWS SDK ，因此會發生此錯誤。此問題在 2.27.19 版中引入，並影響截至 2.27.23 的所有版本。此問題已在 2.27.24 版中 適用於 Java 的 AWS SDK 解決。為了獲得最佳效能和穩定性，建議您升級至 2.28.0 版或更新版本。

## 對消費者的其他常見問題進行故障診斷
<a name="misc-troubleshooting-consumer"></a>
+ [為何 Kinesis Data Streams 觸發器無法調用我的 Lambda 函數？](https://aws.amazon.com/premiumsupport/knowledge-center/kinesis-data-streams-lambda-invocation/)
+ [如何偵測並疑難排解 Kinesis Data Streams 中的 ReadProvisionedThroughputExceeded 例外狀況？](https://aws.amazon.com/premiumsupport/knowledge-center/kinesis-readprovisionedthroughputexceeded/) 
+ [為何我遇到 Kinesis Data Streams 的高延遲問題？](https://aws.amazon.com/premiumsupport/knowledge-center/kinesis-data-stream-latency-issues/)
+ [為何我的 Kinesis 資料串流會傳回 500 個內部伺服器錯誤？](https://aws.amazon.com/premiumsupport/knowledge-center/kinesis-data-stream-500-error/)
+ [如何對遭 Kinesis Data Streams 封鎖或停滯的 KCL 應用程式進行故障診斷？](https://aws.amazon.com/premiumsupport/knowledge-center/kcl-kinesis-data-streams/)
+ [是否可以將不同的 Amazon Kinesis 用戶端程式庫應用程式與相同的 Amazon DynamoDB 資料表搭配使用？](https://aws.amazon.com/premiumsupport/knowledge-center/kinesis-kcl-apps-dynamodb-table/)