本頁面說明 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
指令會重試「回應」一節中列出的錯誤,您不必採取其他動作。您可能需要針對其他錯誤採取行動,例如:
憑證無效或權限不足。
Proxy 設定有問題,因此無法連上網路。
如果發生可重試的錯誤,gcloud CLI 會使用部分二進位指數輪詢策略重試要求。gcloud CLI 的預設重試次數上限為 32 次。
用戶端程式庫
C++
根據預設,作業支援下列 HTTP 錯誤碼的重試,以及任何表示連線中斷或從未成功建立的通訊端錯誤。
408 Request Timeout
429 Too Many Requests
500 Internal Server Error
502 Bad Gateway
503 Service Unavailable
504 Gateway Timeout
C++ 程式庫中的所有指數輪詢和重試設定都可以設定。如果程式庫中實作的演算法無法滿足您的需求,您可以提供自訂程式碼來實作自己的策略。
設定 | 預設值 |
---|---|
自動重試 | 是 |
重試要求的時間上限 | 15 分鐘 |
初始等待 (輪詢) 時間 | 1 秒 |
每次疊代的等待時間乘數 | 2 |
等待時間上限 | 5 分鐘 |
根據預設,C++ 程式庫會重試所有作業,即使作業從未具備等冪性,且重複成功時可能會刪除或建立多個資源,也會重試。如要只重試等冪作業,請使用 google::cloud::storage::StrictIdempotencyPolicy
類別。
C#
C# 用戶端程式庫預設使用指數輪詢。
Go
根據預設,作業支援下列錯誤的重試作業:
- 連線錯誤:
io.ErrUnexpectedEOF
:這可能是暫時性網路問題所致。url.Error
含有connection refused
:這可能是暫時性的網路問題所致。- 包含
connection reset by peer
的url.Error
: 這表示 Google Cloud 已重設連線。 net.ErrClosed
:這表示 Google Cloud 已關閉連線。
- HTTP 程式碼:
408 Request Timeout
429 Too Many Requests
500 Internal Server Error
502 Bad Gateway
503 Service Unavailable
504 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
- 如果方法會在 JSON 要求主體中插入
etag
,則可以安全地重試。僅在已設定HmacKeyMetadata.Etag
時,用於HMACKeyHandle.Update
。
- 如果方法會在 JSON 要求主體中插入
RetryPolicy
預設為 RetryPolicy.RetryIdempotent
。如要瞭解如何修改預設重試行為,請參閱「自訂重試」一文中的範例。
Java
根據預設,作業支援下列錯誤的重試作業:
- 連線錯誤:
Connection reset by peer
:這表示 Google Cloud 已重設連線。Unexpected connection closure
:這表示 Google Cloud 已關閉連線。
- HTTP 程式碼:
408 Request Timeout
429 Too Many Requests
500 Internal Server Error
502 Bad Gateway
503 Service Unavailable
504 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 Timeout
429 Too Many Requests
500 Internal Server Error
502 Bad Gateway
503 Service Unavailable
504 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 用戶端程式庫預設使用指數輪詢。
Python
根據預設,作業支援下列錯誤代碼的重試作業:
- 連線錯誤:
requests.exceptions.ConnectionError
requests.exceptions.ChunkedEncodingError
(僅適用於擷取或傳送酬載資料至物件的作業,例如上傳和下載)ConnectionError
http.client.ResponseNotReady
urllib3.exceptions.TimeoutError
- HTTP 程式碼:
408 Request Timeout
429 Too Many Requests
500 Internal Server Error
502 Bad Gateway
503 Service Unavailable
504 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 要求主體中插入
Ruby
根據預設,作業支援下列錯誤代碼的重試作業:
- 連線錯誤:
SocketError
HTTPClient::TimeoutError
Errno::ECONNREFUSED
HTTPClient::KeepAliveDisconnected
- HTTP 程式碼:
408 Request Timeout
429 Too Many Requests
5xx 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
您無法自訂 PHP 用戶端程式庫使用的預設重試策略。
Python
如要修改預設重試行為,請呼叫 with_XXX
方法,建立 google.cloud.storage.retry.DEFAULT_RETRY
物件的副本。如果您加入 DEFAULT_RETRY
參數,Python 用戶端程式庫會自動使用輪詢策略重試要求。
請注意,系統不支援對物件擷取或傳送酬載資料的作業 (例如上傳和下載)。with_predicate
建議您逐一修改屬性。詳情請參閱 google-api-core Retry 參考資料。
如要設定自己的條件式重試,請建立 ConditionalRetryPolicy
物件,並使用 DEFAULT_RETRY_IF_GENERATION_SPECIFIED
、DEFAULT_RETRY_IF_METAGENERATION_SPECIFIED
或 DEFAULT_RETRY_IF_ETAG_IN_JSON
包裝自訂 Retry
物件。
請參閱下列程式碼範例,瞭解如何自訂重試行為。
Ruby
初始化儲存空間用戶端時,所有重試設定都會設為上表顯示的值。如要修改預設重試行為,請在初始化儲存空間用戶端時傳遞重試設定。
如要覆寫特定作業的重試次數,請在作業的 options
參數中傳遞 retries
。
REST API
指數輪詢演算法
指數輪詢演算法會以指數方式重試要求,並將每次要求之間的等待時間逐漸增加至最大輪詢時間,一般來說,您應使用指數輪詢和抖動,重試符合回應和等冪條件的要求。如要瞭解如何以指數輪詢方式自動重試,請參閱解決連鎖故障問題。
重試反模式
建議您視情況使用或自訂內建重試機制;請參閱自訂重試。無論您是使用預設重試機制、自訂機制,還是實作自己的重試邏輯,都必須避免下列常見的反模式,因為這些模式可能會加劇問題,而非解決問題。
不輪詢直接重試
立即重試要求或延遲時間很短,可能會導致連鎖性故障,也就是說,故障可能會觸發其他故障。
如何避免這個問題:實作指數輪詢和抖動。這項策略會逐步增加重試之間的等待時間,並加入隨機元素,避免重試次數過多導致服務過載。
無條件重試非等冪作業
重複執行非等冪作業可能會導致非預期的副作用,例如非預期的資料覆寫或刪除。
如何避免這個問題:請詳閱「作業的等冪性」一節,徹底瞭解各項作業的等冪性特徵。對於非等冪作業,請確保重試邏輯可以處理潛在的重複項目,或完全避免重試。請謹慎重試,以免導致競爭狀況。
重試無法重試的錯誤
將所有錯誤視為可重試的錯誤可能會造成問題。舉例來說,授權失敗或無效要求等錯誤會持續發生,如果未解決根本原因就重試,將不會成功,且可能導致應用程式陷入無限迴圈。
如何避免這種情況:將錯誤分為暫時性 (可重試) 和永久性 (不可重試)。請只重試暫時性錯誤,例如 408
、429
和 5xx
HTTP 代碼,或特定連線問題。如果是永久性錯誤,請記錄下來並妥善處理根本原因。
忽略重試次數上限
無限期重試可能會導致應用程式耗盡資源,或持續向不會自行復原的服務傳送要求。
如何避免這種情況:根據工作負載的性質調整重試次數上限。如為對延遲時間較敏感的工作負載,請考慮設定重試時間上限,確保及時回應或失敗。如果是批次工作負載,可能可以容許暫時性伺服器端錯誤的重試時間較長,建議您設定較高的重試次數上限。
不必要地分層重試
在現有的重試機制上新增自訂應用程式層級的重試邏輯,可能會導致重試次數過多。舉例來說,如果應用程式重試作業三次,而基礎用戶端程式庫也會針對應用程式的每次嘗試重試三次,您最終可能會重試九次。如果針對無法重試的錯誤傳送大量重試要求,可能會導致要求遭到節流,進而限制所有工作負載的輸送量。重試次數過多也可能導致要求延遲,但成功率不會提高。
如何避免這種情況:建議您使用及設定內建的重試機制。如果必須實作應用程式層級的重試機制 (例如針對跨多項作業的特定商業邏輯),請務必清楚瞭解底層的重試行為。建議您在其中一個層級中停用或大幅限制重試次數,避免乘法效應。
後續步驟
- 進一步瞭解要求前提條件。