診斷和排解 Azure Cosmos DB .NET SDK 要求逾時例外狀況

適用於:NoSQL

如果 SDK 在發生逾時限制之前無法完成要求,就會發生 HTTP 408 錯誤。

應用程式設計必須遵循我們的使用 Azure Cosmos DB SDK 設計彈性應用程式的指南,以確保其正確回應不同的網路狀況。 您的應用程式應該能夠針對逾時錯誤進行重試,因為這些錯誤是分散式系統中的預期錯誤。

評估逾時錯誤的情況時:

  • 相較於作業成功時,目前所影響的作業量為何? 受影響作業是否在服務 SLA 內?
  • P99 延遲 / 可用性是否受到影響?
  • 失敗會影響所有應用程式執行個體還是只會影響子集? 當問題縮減為執行個體的子集時,通常是與這些執行個體相關的問題。

自訂 Azure Cosmos DB .NET SDK 上的逾時

SDK 有兩種不同的替代方式可供控制逾時,每種各有不同的範圍。

要求層級逾時

CosmosClientOptions.RequestTimeout (或適用於 SDK v2 的 ConnectionPolicy.RequestTimeout) 設定可讓您在要求離開 SDK 且位於網路上之後設定網路要求的逾時,直到收到回應為止。

CosmosClientOptions.OpenTcpConnectionTimeout (或適用於 SDK v2 的 ConnectionPolicy.OpenTcpConnectionTimeout) 設定可讓您針對開啟初始連線時所花費的時間設定逾時。 開啟連線之後,後續要求將會使用該連線。

使用者啟動的作業可以跨越多個網路要求 (例如,重試)。 這兩個設定是根據要求,而不是作業的端對端。

CancellationToken

SDK 中的所有非同步作業都有選擇性的 CancellationToken 參數。 整個作業進行期間 (跨所有網路要求和重試) 都會使用這個 CancellationToken 參數。 在兩個網路要求之間,如果相關權杖已過期,則可能會檢查取消權杖,並取消作業。 應使用取消權杖來定義作業範圍的大致預期逾時值。

注意

CancellationToken 參數是一種機制,當程式庫不會造成無效狀態時,便會檢查取消。 作業可能不會剛好在取消中所定義的時間到達時就取消。 相反地,在時間到達之後,作業會在可安全取消時再取消。

疑難排解步驟

下列清單包含要求逾時例外狀況的已知原因和解決方案。

CosmosOperationCanceledException

當您的應用程式將 CancellationTokens 傳遞至 SDK 作業時,這種例外狀況很常見。 SDK 會在重試之間檢查 CancellationToken 的狀態,如果 CancellationToken 的狀態是已取消,則會以此例外狀況中止目前的作業。

例外狀況的 Message / ToString() 也會透過 Cancellation Token has expired: true 指出 CancellationToken 的狀態,其中也會包含診斷,而診斷中會有相關要求的取消內容。

您可以放心地在這些例外狀況上進行重試,而且從重試的觀點看,這些例外狀況可以視為逾時

解決方案

確認 CancellationToken 中設定的時間,確定該時間大於您的 RequestTimeoutCosmosClientOptions.OpenTcpConnectionTimeout (如果您使用直接模式)。 如果 CancellationToken 中的可用時間小於設定的逾時,且 SDK 遇到暫時性連線問題,則 SDK 將無法重試,而且會擲回 CosmosOperationCanceledException

高 CPU 使用率

高 CPU 使用率是最常見的情況。 為了達到最佳延遲,CPU 使用率應保持在約 40% 之間。 請使用 10 秒的間隔來監視最大 (非平均) CPU 使用率。 跨分割查詢最容易遇到 CPU 尖峰問題,因為其可能會為單一查詢進行多個連線。

逾時會包含「診斷」,其中包含:

"systemHistory": [
{
"dateUtc": "2021-11-17T23:38:28.3115496Z",
"cpu": 16.731,
"memory": 9024120.000,
"threadInfo": {
"isThreadStarving": "False",
....
}

},
{
"dateUtc": "2021-11-17T23:38:28.3115496Z",
"cpu": 16.731,
"memory": 9024120.000,
"threadInfo": {
"isThreadStarving": "False",
....
}

},
...
]
  • 如果 cpu 值超過 70%,則逾時可能起因於 CPU 耗盡。 在此情況下,解決方案是調查高 CPU 使用率的來源並將其降低,或將電腦調整為較大的資源大小。
  • 如果 threadInfo/isThreadStarving 節點有 True 值,則原因是執行緒耗盡。 在此情況下,解決方案是調查執行緒耗盡的來源 (可能已鎖定的執行緒),或將電腦調整為較大的資源大小。
  • 如果測量之間的 dateUtc 時間不是 10 秒左右,則也表示執行緒集區有爭用情形。 CPU 以每 10 秒排入執行緒集區中的獨立工作來測量,如果測量之間的時間較長,則表示無法及時處理非同步工作。 最常見的情況是在應用程式的程式碼中透過非同步程式碼來封鎖呼叫

解決方案

應該擴大或擴增使用 SDK 的用戶端應用程式。

通訊端或連接埠可用性可能很低

在 Azure 中執行時,使用 .NET SDK 的用戶端可能會達到 Azure SNAT (PAT) 連接埠耗盡。

解決方案 1

如果您是在 Azure VM 上執行,請遵循 SNAT 連接埠耗盡指南

解決方案 2

如果您是在 Azure App Service 上執行,請遵循連線錯誤疑難排解指南使用 App Service 診斷

解決方案 3

如果您是在 Azure Functions 上執行,請驗證您有遵循針對所有相關服務 (包含 Azure Cosmos DB) 維護 singleton 或靜態用戶端提出的 Azure Functions 建議。 請根據您函數應用程式裝載的類型與大小,查看服務限制

解決方案 4

如果您使用 HTTP Proxy,請確定它可以支援在 SDK ConnectionPolicy 中設定的連線數目。 否則就會遇到連線問題。

建立多個用戶端執行個體

建立多個用戶端執行個體可能會導致連線競爭或逾時問題。 診斷包含兩個相關屬性:

{
    "NumberOfClientsCreated":X,
    "NumberOfActiveClients":Y,
}

NumberOfClientsCreated 會追蹤已在相同 AppDomain 內建立 CosmosClient 的次數,而 NumberOfActiveClients 會追蹤作用中用戶端 (未處置)。 預期是,如果遵循單一模式,則 X 會符合應用程式所使用的帳戶數目,而且 X 等於 Y

如果 X 大於 Y,則表示應用程式正在建立和處置用戶端執行個體。 這可能會導致連線競爭和/或 CPU 競爭

解決方案

遵循效能秘訣,並跨整個程序使用每個帳戶的單一 CosmosClient 執行個體。 避免建立和處置用戶端。

經常性分割區索引鍵

Azure Cosmos DB 會將整體佈建的輸送量平均散發到實體分割區。 當有經常性分割區時,實體分割區上的一或多個邏輯分割區索引鍵會取用實體分割區的所有每秒要求單位 (RU/秒)。 同時,將不會使用其他實體分割區上的 RU/秒。 徵兆是取用的總 RU/秒將小於資料庫或容器的整體佈建 RU/秒,但您仍會在對經常性邏輯分割區索引鍵的要求上看到節流 (429 秒)。 請使用標準化 RU 使用量計量來查看工作負載是否遇到經常性分割區。

解決方案

選擇可平均散發要求磁碟區和儲存體的良好分割區索引鍵。 了解如何變更分割區索引鍵

高度並行

應用程式正在進行高度並行,這可能會導致通道上發生競爭。

解決方案

應該擴大或擴增使用 SDK 的用戶端應用程式。

大型要求或回應

大型要求或回應可能會導致通道上發生隊頭阻塞並加劇競爭問題,即使有相對低度的並行也是如此。

解決方案

應該擴大或擴增使用 SDK 的用戶端應用程式。

失敗率在 Azure Cosmos DB SLA 內

應用程式應該能夠處理暫時性失敗,並在必要時重試。 因為在建立路徑尚無法得知服務是否建立了項目,所以不會重試任何 408 例外狀況。 重新傳送相同的項目進行建立,將導致衝突例外狀況。 使用者應用程式商務邏輯可能有自訂邏輯能處理衝突,這能打斷現有項目與建立重試所產生之衝突之間的混淆。

失敗率違反 Azure Cosmos DB SLA

請連絡 Azure 支援

下一步