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 秒 |
| 初始 RPC 逾時 | 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- 如果方法將
etag插入 JSON 要求主體,則可安全重試。如果是HMACKeyMetadata.update(),則必須在HMACKeyMetadata物件本身設定 etag。對於其他類別的set_iam_policy()方法,這表示必須在傳遞至方法的「policy」引數中設定 etag。
- 如果方法將
小茹
根據預設,作業支援重試下列錯誤代碼:
- 連線錯誤:
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 物件。
請參閱下列程式碼範例,瞭解如何自訂重試行為。
小茹
初始化 Storage 用戶端時,所有重試設定都會設為上表所示的值。如要修改預設重試行為,請在初始化儲存空間用戶端時傳遞重試設定。
如要覆寫特定作業的重試次數,請在作業的 options 參數中傳遞 retries。
REST API
使用指數輪詢演算法實作自己的重試策略。
指數輪詢演算法
指數輪詢演算法會重試要求,並以指數方式增加要求之間的等待時間,直到達到最大輪詢時間。一般來說,您應使用指數輪詢和隨機延遲時間,重試符合回應和冪等性條件的要求。如要瞭解使用指數輪詢實作自動重試的最佳做法,請參閱「解決串聯故障」。
重試反面模式
建議您在適用情況下使用或自訂內建重試機制,詳情請參閱「自訂重試」。無論您是使用預設重試機制、自訂機制,還是自行實作重試邏輯,都應避免下列常見的反模式,因為這些模式可能會加劇問題,而非解決問題。
重試 (不採用輪詢機制)
不建議:立即重試要求或延遲時間過短,可能會導致連鎖故障,也就是可能觸發其他故障的故障。
如何避免這種情況:實作指數輪詢和隨機延遲。這種策略會逐步增加重試之間的等待時間,並加入隨機元素,避免重試次數過多而導致服務超載。
無條件重試非冪等作業
不建議:重複執行非冪等作業可能會導致非預期的副作用,例如意外覆寫或刪除資料。
如何避免:請詳閱「作業的冪等性」一節,徹底瞭解每項作業的冪等性特徵。對於非冪等作業,請確保重試邏輯能處理潛在的重複作業,或完全避免重試。請謹慎重試,以免發生競爭狀況。
重試無法重試的錯誤
不建議:將所有錯誤視為可重試,可能會造成問題。部分錯誤 (例如授權失敗或要求無效) 會持續發生。如果未解決根本原因就重試要求,要求將無法成功,且可能導致應用程式陷入無限迴圈。
如何避免:將錯誤分為暫時性 (可重試) 和永久性 (不可重試)。請只重試暫時性錯誤,例如 408、429 和 5xx HTTP 代碼,或特定連線問題。如果是永久性錯誤,請記錄下來,並妥善處理根本原因。
忽略重試限制
不建議:無限期重試可能會導致應用程式資源耗盡,或持續向無法自行復原的服務傳送要求。
如何避免這種情況:根據工作負載的性質,調整重試次數上限。如果工作負載對延遲時間較敏感,建議設定重試時間總長度上限,確保能及時回應或失敗。如果是批次工作負載,可能可以容忍較長的重試期,以因應暫時性伺服器端錯誤,因此建議設定較高的重試總次數上限。
不必要的重試分層
不建議:在現有重試機制上新增自訂應用程式層級重試邏輯,可能會導致重試次數過多。舉例來說,如果應用程式重試某項作業三次,而基礎用戶端程式庫也針對應用程式的每次嘗試重試三次,最後可能會重試九次。如果針對無法重試的錯誤傳送大量重試要求,可能會導致要求節流,限制所有工作負載的處理量。重試次數過多也可能增加要求延遲時間,但不會提高成功率。
如何避免這種情況:建議您使用並設定內建的重試機制。如果必須實作應用程式層級重試 (例如跨多項作業的特定商業邏輯),請務必清楚瞭解基礎重試行為。建議您停用或大幅限制其中一個層級的重試次數,以免產生乘數效應。
後續步驟
- 進一步瞭解要求前置條件。