本頁面說明 Cloud Storage 工具如何重試失敗的要求,以及如何自訂重試行為。此外,也會說明重試要求時的注意事項。
總覽
有兩項因素會決定是否能安全地重試要求:
您從要求收到的回應。
要求的冪等性。
回應
您從要求收到的回應會指出重試要求是否有用。與暫時性問題相關的回應通常可以重試。另一方面,與永久錯誤相關的回應表示您需要進行變更 (例如授權或設定變更),才能再次嘗試要求。下列回應表示發生暫時性問題,建議重試:
- HTTP
408、429和5xx回應代碼。 - 通訊端逾時和 TCP 中斷連線。
冪等
冪等要求可以重複執行,不會變更目標資源的最終狀態,因此每次都會產生相同的最終狀態。舉例來說,清單作業一律為冪等,因為這類要求不會修改資源。另一方面,建立新的 Pub/Sub 通知絕不會是等冪作業,因為每次要求成功時,系統都會建立新的通知 ID。
以下是讓作業具備等冪性的條件範例:
即使持續要求,該作業對目標資源產生的可觀測效果仍相同。
這項作業只會成功一次。
這項作業對目標資源的狀態沒有明顯影響。
收到可重試的回應時,請考量要求的冪等性,因為重試非冪等要求可能會導致競爭狀況和其他衝突。
條件式冪等性
部分要求屬於「條件式冪等」,也就是說,只有在包含特定選用引數時,才具備冪等性。如果作業在特定條件下可安全重試,則預設只有在條件成立時才應重試。Cloud Storage 接受前置條件和 ETag 做為要求的條件。
作業的冪等性
下表列出各冪等性類別中的 Cloud Storage 作業。
| 冪等 | 作業 |
|---|---|
| 一律冪等 |
|
| 有條件冪等 |
|
| 永不冪等 |
|
1這個欄位可在 JSON API 中使用。如要瞭解用戶端程式庫中可用的欄位,請參閱相關的用戶端程式庫說明文件。
Cloud Storage 工具如何實作重試策略
控制台
Google Cloud 控制台會代您向 Cloud Storage 傳送要求,並處理任何必要的輪詢。
指令列
gcloud storage 指令會重試「Response」(回應) 區段中列出的錯誤,您不需採取其他動作。您可能需要採取行動來解決其他錯誤,例如:
憑證無效或權限不足。
Proxy 設定有問題,因此無法連上網路。
如果是可重試的錯誤,gcloud CLI 會使用截斷二進位指數輪詢策略重試要求。gcloud CLI 的預設重試次數上限為 32 次。
用戶端程式庫
C++
根據預設,作業支援下列 HTTP 錯誤代碼的重試作業,以及任何表示連線中斷或從未成功建立的通訊端錯誤。
408 Request Timeout429 Too Many Requests500 Internal Server Error502 Bad Gateway503 Service Unavailable504 Gateway Timeout
C++ 程式庫中的所有指數輪詢和重試設定皆可調整。如果程式庫中實作的演算法不符合您的需求,可以提供自訂程式碼來實作自己的策略。
| 設定 | 預設值 |
|---|---|
| 自動重試 | 是 |
| 重試要求的時間上限 | 15 分鐘 |
| 初始等待 (退避) 時間 | 1 秒 |
| 每次疊代的等待時間調節係數 | 2 |
| 等待時間上限 | 5 分鐘 |
根據預設,C++ 程式庫會重試所有作業,即使這些作業永遠不會是等冪作業,且重複成功時可能會刪除或建立多個資源,也會重試。如要只重試冪等作業,請使用 google::cloud::storage::StrictIdempotencyPolicy 類別。
C#
C# 用戶端程式庫預設會使用指數輪詢。
Go
根據預設,作業支援重試下列錯誤:
- 連線錯誤:
io.ErrUnexpectedEOF:這可能是暫時性網路問題所致。url.Error包含connection refused:這可能是暫時性網路問題所致。url.Error包含connection reset by peer: 這表示 Google Cloud 已重設連線。net.ErrClosed:這表示 Google Cloud 已關閉連線。
- HTTP 代碼:
408 Request Timeout429 Too Many Requests500 Internal Server Error502 Bad Gateway503 Service Unavailable504 Gateway Timeout
- 實作
Temporary()介面並提供err.Temporary() == true值的錯誤 - 使用 Go 1.13 錯誤包裝包裝的任何上述錯誤
Go 程式庫中的所有指數輪詢設定皆可設定。 根據預設,Go 中的作業會使用下列指數輪詢設定 (預設值取自 gax):
| 設定 | 預設值 (秒) |
|---|---|
| 自動重試 | 如果為冪等,則為 True |
| 嘗試次數上限 | 不限 |
| 初始重試延遲時間 | 1 秒 |
| 重試延遲時間倍數 | 2.0 |
| 重試延遲時間上限 | 30 秒 |
| 總逾時 (支援續傳的上傳作業區塊) | 32 秒 |
| 總逾時 (所有其他作業) | 不限 |
一般來說,除非控制情境取消、用戶端關閉或收到非暫時性錯誤,否則系統會無限期重試。如要停止重試,請使用內容逾時或取消。唯一的例外情況是使用 Writer 執行支援續傳的上傳作業,且資料量大到需要多個要求。在這種情況下,每個區塊預設會在 32 秒後逾時並停止重試。您可以變更 Writer.ChunkRetryDeadline 來調整預設逾時時間。
Go 作業的子集具有條件式冪等性 (在特定條件下可安全重試)。只有在符合特定條件時,這些作業才會重試:
GenerationMatch或Generation- 如果對呼叫套用了
GenerationMatch前置條件,或已設定ObjectHandle.Generation,則可安全地重試。
- 如果對呼叫套用了
MetagenerationMatch- 如果呼叫套用了
MetagenerationMatch前置條件,可以安全地重試。
- 如果呼叫套用了
Etag- 如果方法將
etag插入 JSON 要求主體,則可安全重試。只有在設定HmacKeyMetadata.Etag時,才會在HMACKeyHandle.Update中使用。
- 如果方法將
RetryPolicy 預設為 RetryPolicy.RetryIdempotent。如需修改預設重試行為的範例,請參閱「自訂重試」。
Java
根據預設,作業支援下列錯誤的重試功能:
- 連線錯誤:
Connection reset by peer:這表示 Google Cloud 已重設連線。Unexpected connection closure:這表示 Google Cloud 已關閉連線。
- HTTP 狀態碼:
408 Request Timeout429 Too Many Requests500 Internal Server Error502 Bad Gateway503 Service Unavailable504 Gateway Timeout
Java 程式庫中的所有指數輪詢設定皆可調整。根據預設,透過 Java 執行的作業會使用下列指數輪詢設定:
| 設定 | 預設值 (秒) |
|---|---|
| 自動重試 | 如果為冪等,則為 True |
| 嘗試次數上限 | 6 |
| 初始重試延遲時間 | 1 秒 |
| 重試延遲時間倍數 | 2.0 |
| 重試延遲時間上限 | 32 秒 |
| 總逾時 | 50 秒 |
| 初始遠端程序呼叫逾時 | 50 秒 |
| RPC 逾時乘數 | 1.0 |
| RPC 逾時時間上限 | 50 秒 |
| 連線逾時 | 20 秒 |
| 讀取逾時 | 20 秒 |
如要進一步瞭解相關設定,請參閱 RetrySettings.Builder 和 HttpTransportOptions.Builder 的 Java 參考說明文件。
有部分 Java 作業是條件式冪等 (條件式安全重試)。只有在包含特定引數時,這些作業才會重試:
ifGenerationMatch或generation- 如果將
ifGenerationMatch或generation做為選項傳遞至方法,則可安全重試。
- 如果將
ifMetagenerationMatch- 如果
ifMetagenerationMatch是以選項形式傳入,可以安全地重試。
- 如果
StorageOptions.setStorageRetryStrategy 預設為 StorageRetryStrategy#getDefaultStorageRetryStrategy。如需如何修改預設重試行為的範例,請參閱「自訂重試」。
Node.js
根據預設,作業支援重試下列錯誤代碼:
- 連線錯誤:
EAI_again:這是 DNS 查詢錯誤。詳情請參閱getaddrinfo說明文件。Connection reset by peer:這表示 Google Cloud 已重設連線。Unexpected connection closure:這表示 Google Cloud 已關閉連線。
- HTTP 代碼:
408 Request Timeout429 Too Many Requests500 Internal Server Error502 Bad Gateway503 Service Unavailable504 Gateway Timeout
Node.js 程式庫中的所有指數輪詢設定皆可調整。根據預設,透過 Node.js 執行的作業會使用下列指數輪詢設定:
| 設定 | 預設值 (秒) |
|---|---|
| 自動重試 | 如果為等冪,則為 True |
| 重試次數上限 | 3 |
| 初始等待時間 | 1 秒 |
| 每次疊代的等待時間調節係數 | 2 |
| 等待時間上限 | 64 秒 |
| 預設截止日期 | 600 秒 |
Node.js 作業的子集具有條件式冪等性 (在特定條件下可安全重試)。只有在包含特定引數時,這些作業才會重試:
ifGenerationMatch或generation- 如果將
ifGenerationMatch或generation做為選項傳遞至方法,則可安全重試。方法通常只接受這兩個參數的其中一個。
- 如果將
ifMetagenerationMatch- 如果
ifMetagenerationMatch是以選項形式傳入,可以安全地重試。
- 如果
retryOptions.idempotencyStrategy 預設設為 IdempotencyStrategy.RetryConditional。如需修改預設重試行為的範例,請參閱「自訂重試」。
PHP
PHP 用戶端程式庫預設會使用指數輪詢。
根據預設,作業支援重試下列錯誤代碼:
- 連線錯誤:
connetion-refused:這可能是暫時性的網路問題所致。connection-reset:這表示 Google Cloud 已重設連線。
- HTTP 代碼:
200:適用於部分下載案例408 Request Timeout429 Too Many Requests500 Internal Server Error502 Bad Gateway503 Service Unavailable504 Gateway Timeout
PHP 程式庫中的部分指數輪詢設定可以調整。根據預設,透過 PHP 執行的作業會使用下列指數輪詢設定:
| 設定 | 預設值 (秒) |
|---|---|
| 自動重試 | 如果為冪等,則為 True |
| 初始重試延遲時間 | 1 秒 |
| 重試延遲時間倍數 | 2.0 |
| 重試延遲時間上限 | 60 秒 |
| 要求逾時 | REST 為 0,gRPC 為 60 |
| 預設重試次數 | 3 |
有一組 PHP 作業子集,在特定條件下具有冪等性 (在特定條件下可安全重試)。只有在這些作業包含特定引數時,才會重試:
ifGenerationMatch或generation- 如果將
ifGenerationMatch或generation做為選項傳遞至方法,則可安全重試。方法通常只接受這兩個參數的其中一個。
- 如果將
ifMetagenerationMatch- 如果傳入
ifMetagenerationMatch做為選項,則可安全重試。
- 如果傳入
建立 StorageClient 時,系統預設會使用 StorageClient::RETRY_IDEMPOTENT 策略。如需如何修改預設重試行為的範例,請參閱「自訂重試」。
Python
根據預設,作業支援下列錯誤代碼的重試:
- 連線錯誤:
requests.exceptions.ConnectionErrorrequests.exceptions.ChunkedEncodingError(僅適用於擷取或傳送酬載資料至物件的作業,例如上傳和下載)ConnectionErrorhttp.client.ResponseNotReadyurllib3.exceptions.TimeoutError
- HTTP 代碼:
408 Request Timeout429 Too Many Requests500 Internal Server Error502 Bad Gateway503 Service Unavailable504 Gateway Timeout
透過 Python 執行的作業會使用下列指數輪詢預設設定:
| 設定 | 預設值 (秒) |
|---|---|
| 自動重試 | 如果為冪等,則為 True |
| 初始等待時間 | 1 |
| 每次疊代的等待時間調節係數 | 2 |
| 等待時間上限 | 60 |
| 預設截止日期 | 120 |
除了一律為冪等的 Cloud Storage 作業外,Python 用戶端程式庫預設會自動重試 Objects: insert、Objects: delete 和 Objects: patch。
如果包含特定引數,部分 Python 作業會成為有條件的等冪作業 (可安全地重試)。只有在條件案例通過時,這些作業才會重試:
DEFAULT_RETRY_IF_GENERATION_SPECIFIED- 如果
generation或if_generation_match做為引數傳遞至方法,則可安全重試。方法通常只接受這兩個參數的其中一個。
- 如果
DEFAULT_RETRY_IF_METAGENERATION_SPECIFIED- 如果
if_metageneration_match做為引數傳遞至方法,則可安全重試。
- 如果
DEFAULT_RETRY_IF_ETAG_IN_JSON- 如果方法會在 JSON 要求主體中插入
etag,則可以安全地重試。如果是HMACKeyMetadata.update(),則必須在HMACKeyMetadata物件本身設定 etag。對於其他類別的set_iam_policy()方法,這表示必須在傳遞至方法的「policy」引數中設定 etag。
- 如果方法會在 JSON 要求主體中插入
小茹
根據預設,作業支援下列錯誤代碼的重試:
- 連線錯誤:
SocketErrorHTTPClient::TimeoutErrorErrno::ECONNREFUSEDHTTPClient::KeepAliveDisconnected
- HTTP 代碼:
408 Request Timeout429 Too Many Requests5xx Server Error
Ruby 用戶端程式庫中的所有指數輪詢設定都可設定。根據預設,透過 Ruby 用戶端程式庫執行的作業會使用下列指數輪詢設定:
| 設定 | 預設值 |
|---|---|
| 自動重試 | 是 |
| 重試次數上限 | 3 |
| 初始等待時間 | 1 秒 |
| 每次疊代的等待時間調節係數 | 2 |
| 等待時間上限 | 60 秒 |
| 預設期限 | 900 秒 |
Ruby 作業子集在包含特定引數時,具有條件式冪等性 (在特定條件下可安全重試):
if_generation_match或generation- 如果
generation或if_generation_match參數做為引數傳遞至方法,則可安全重試。方法通常只接受這兩個參數之一。
- 如果
if_metageneration_match- 如果
if_metageneration_match參數是以選項形式傳入,則可安全重試。
- 如果
根據預設,系統會重試所有等冪作業,且只有在條件案例通過時,才會重試有條件的等冪作業。系統不會重試非等冪作業。如需如何修改預設重試行為的範例,請參閱「自訂重試」。
REST API
直接呼叫 JSON 或 XML API 時,您應使用指數輪詢演算法,自行導入重試策略。
自訂重試
控制台
您無法使用 Google Cloud 控制台自訂重試行為。
指令列
如要控制 gcloud storage 指令的重試策略,請建立命名設定,並設定下列部分或所有屬性:
| 設定 | 預設值 (以秒為單位) |
|---|---|
base_retry_delay |
1 |
exponential_sleep_multiplier |
2 |
max_retries |
32 |
max_retry_delay |
32 |
接著,您可以使用 --configuration 專案層級旗標,在每個指令中套用定義的設定,或使用 gcloud config set 指令,在所有 Google Cloud CLI 指令中套用定義的設定。
用戶端程式庫
C++
如要自訂重試行為,請在初始化 google::cloud::storage::Client 物件時,為下列選項提供值:
google::cloud::storage::RetryPolicyOption:程式庫提供google::cloud::storage::LimitedErrorCountRetryPolicy和google::cloud::storage::LimitedTimeRetryPolicy類別。您可以提供自己的類別,但必須實作google::cloud::RetryPolicy介面。google::cloud::storage::BackoffPolicyOption:這個程式庫提供google::cloud::storage::ExponentialBackoffPolicy類別。您可以提供自己的類別,但必須實作google::cloud::storage::BackoffPolicy介面。google::cloud::storage::IdempotencyPolicyOption:程式庫提供google::cloud::storage::StrictIdempotencyPolicy和google::cloud::storage::AlwaysRetryIdempotencyPolicy類別。您可以提供自己的類別,但必須實作google::cloud::storage::IdempotencyPolicy介面。
詳情請參閱 C++ 用戶端程式庫參考文件。
C#
您無法自訂 C# 用戶端程式庫使用的預設重試策略。
Go
初始化儲存空間用戶端時,系統會設定預設重試設定。除非遭到覆寫,否則設定中的選項會設為預設值。使用者可以為單一程式庫呼叫設定非預設的重試行為 (使用 BucketHandle.Retryer 和 ObjectHandle.Retryer),也可以為用戶端發出的所有呼叫設定重試行為 (使用 Client.SetRetry)。如要修改重試行為,請將相關的 RetryOptions 傳遞至其中一個方法。
請參閱下列程式碼範例,瞭解如何自訂重試行為。
Java
初始化 Storage 時,系統也會初始化 RetrySettings 的執行個體。除非遭到覆寫,否則 RetrySettings 中的選項會設為預設值。如要修改預設的自動重試行為,請將自訂 StorageRetryStrategy 傳遞至用於建構 Storage 執行個體的 StorageOptions。如要修改任何其他純量參數,請將自訂 RetrySettings 傳遞至用於建構 Storage 例項的 StorageOptions。
請參閱以下範例,瞭解如何自訂重試行為:
Node.js
初始化 Cloud Storage 時,系統也會初始化 retryOptions 設定檔。除非遭到覆寫,否則設定中的選項會設為預設值。如要修改預設重試行為,請在初始化時,將自訂重試設定 retryOptions 傳遞至儲存空間建構函式。Node.js 用戶端程式庫可自動使用退避策略,透過 autoRetry 參數重試要求。
請參閱下列程式碼範例,瞭解如何自訂重試行為。
PHP
初始化儲存空間用戶端時,系統會設定預設重試設定。除非遭到覆寫,否則設定中的選項會設為預設值。使用者可以透過陣列傳遞覆寫選項,為用戶端或單一作業呼叫設定非預設的重試行為。
請參閱下列程式碼範例,瞭解如何自訂重試行為。
Python
如要修改預設重試行為,請呼叫 with_BEHAVIOR 方法,建立 google.cloud.storage.retry.DEFAULT_RETRY 物件的副本。如果您加入 DEFAULT_RETRY 參數,Python 用戶端程式庫會自動使用輪詢策略重試要求。
請注意,with_predicate 不支援擷取或傳送酬載資料至物件的操作,例如上傳和下載。建議您逐一修改屬性。詳情請參閱 google-api-core 重試參考資料。
如要設定自己的條件式重試,請建立 ConditionalRetryPolicy 物件,並使用 DEFAULT_RETRY_IF_GENERATION_SPECIFIED、DEFAULT_RETRY_IF_METAGENERATION_SPECIFIED 或 DEFAULT_RETRY_IF_ETAG_IN_JSON 包裝自訂 Retry 物件。
請參閱下列程式碼範例,瞭解如何自訂重試行為。
小茹
初始化儲存空間用戶端時,所有重試設定都會設為上表中的值。如要修改預設重試行為,請在初始化儲存空間用戶端時傳遞重試設定。
如要覆寫特定作業的重試次數,請在作業的 options 參數中傳遞 retries。
REST API
使用指數輪詢演算法,自行實作重試策略。
指數輪詢演算法
指數輪詢演算法會重試要求,並以指數方式增加要求之間的等待時間,直到達到最大輪詢時間。一般來說,您應使用指數輪詢和抖動,重試符合回應和等冪條件的要求。如要瞭解使用指數輪詢實作自動重試的最佳做法,請參閱「解決串聯故障」。
重試反模式
建議您在適用情況下使用或自訂內建重試機制,詳情請參閱「自訂重試」。無論是使用預設重試機制、自訂機制,還是自行實作重試邏輯,都請務必避免下列常見的反模式,以免問題惡化。
不輪詢就重試
如果立即重試要求或延遲時間過短,可能會導致連鎖故障,也就是可能觸發其他故障的故障。
如何避免這種情況:實作指數輪詢和隨機延遲。這種策略會逐步增加重試之間的等待時間,並加入隨機元素,避免重試次數過多而導致服務超載。
無條件重試非冪等作業
如果重複執行非冪等作業,可能會導致非預期的副作用,例如非預期的資料覆寫或刪除。
如何避免:請詳閱「作業的冪等性」一節,徹底瞭解每項作業的冪等性特徵。對於非冪等作業,請確保重試邏輯能處理潛在的重複作業,或完全避免重試。請謹慎重試,以免發生競爭狀況。
重試無法重試的錯誤
如果將所有錯誤都視為可重試,可能會造成問題。有些錯誤 (例如授權失敗或無效要求) 會持續發生,如果未解決根本原因就重試,將無法成功,且可能導致應用程式陷入無限迴圈。
如何避免這種情況:將錯誤分為暫時性 (可重試) 和永久性 (不可重試)。請只重試暫時性錯誤,例如 408、429 和 5xx HTTP 代碼,或特定連線問題。如果是永久性錯誤,請記錄下來,並妥善處理根本原因。
忽略重試次數上限
無限次重試可能會導致應用程式資源耗盡,或持續向無法自行復原的服務傳送要求。
如何避免這種情況:根據工作負載的性質調整重試次數上限。如果工作負載對延遲時間較敏感,建議設定重試時間總長度上限,確保能及時回應或失敗。如果是批次工作負載,可能可以容忍較長的重試期,以因應暫時性伺服器端錯誤,因此建議設定較高的重試總次數上限。
不必要的重試分層
在現有重試機制上,新增自訂應用程式層級重試邏輯,可能會導致重試次數過多。舉例來說,如果應用程式重試作業三次,而基礎用戶端程式庫也會在應用程式每次嘗試時重試三次,您最終可能會重試九次。如果針對無法重試的錯誤傳送大量重試要求,可能會導致要求節流,限制所有工作負載的處理量。重試次數過多也可能導致要求延遲,但成功率不會提高。
如何避免這種情況:建議使用及設定內建的重試機制。如果必須實作應用程式層級的重試機制 (例如針對跨多項作業的特定商業邏輯),請務必清楚瞭解底層的重試行為。建議您停用或大幅限制其中一個層的重試次數,以免產生乘法效應。
後續步驟
- 進一步瞭解要求前置條件。