Java 適用的 Cloud 用戶端程式庫會使用重試機制,處理非預期的暫時性故障 (也就是伺服器暫時無法使用)。多次嘗試後,伺服器可能會成功回應。
雲端服務營運團隊會選取預設重試值。這些重試值是針對每個 RPC 設定。服務可以選擇只為部分 RPC 啟用重試功能。服務的每個 RPC 可能會有不同的設定。
重試參數
用戶端程式庫有兩種重試參數可供設定:
- 重試狀態碼:要重試的狀態碼組合。
- 重試逾時或嘗試次數限制:可設定 RetrySettings 定義限制。
預設 RPC 重試設定位置
預設重試設定定義在產生的 {Client}StubSettings 檔案中。以 Java-Asset v3.64.0 中的 ExportAssets RPC 為例,預設重試設定定義於下列位置:
重試狀態碼:在
AssetServiceStubSettings.java檔案中設定。範例:ImmutableMap.Builder<String, ImmutableSet<StatusCode.Code>> definitions = ImmutableMap.builder(); definitions.put("no_retry_0_codes", ImmutableSet.copyOf(Lists.<StatusCode.Code>newArrayList())); // ... More StatusCode configurations RETRYABLE_CODE_DEFINITIONS = definitions.build();重試參數:在
AssetServiceStubSettings.java檔案中設定。範例:ImmutableMap.Builder<String, RetrySettings> definitions = ImmutableMap.builder(); RetrySettings settings = null; settings = RetrySettings.newBuilder() .setInitialRpcTimeoutDuration(Duration.ofMillis(60000L)) .setRpcTimeoutMultiplier(1.0) .setMaxRpcTimeoutDuration(Duration.ofMillis(60000L)) .setTotalTimeoutDuration(Duration.ofMillis(60000L)) .build(); definitions.put("no_retry_0_params", settings); // ... More RetrySettings configurations RETRY_PARAM_DEFINITIONS = definitions.build();
這兩種設定都會對應至 AssetServiceStubSettings.java 檔案中的 RPC。範例:
builder
.exportAssetsSettings()
.setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("no_retry_0_codes"))
.setRetrySettings(RETRY_PARAM_DEFINITIONS.get("no_retry_0_params"));
用戶端程式庫重試概念
啟用重試功能後,RPC 會多次嘗試,直到呼叫成功為止。如果伺服器傳回 OK狀態碼 (來自 gRPC) 或 2xx 狀態碼 (來自 HttpJson),即為成功呼叫。
嘗試與作業
下列 RetrySettings 設定會修改 RPC 嘗試和作業的重試設定:
settings =
RetrySettings.newBuilder()
.setInitialRetryDelayDuration(Duration.ofMillis(100L))
.setRetryDelayMultiplier(1.3)
.setMaxRetryDelayDuration(Duration.ofMillis(60000L))
.setInitialRpcTimeoutDuration(Duration.ofMillis(60000L))
.setRpcTimeoutMultiplier(1.0)
.setMaxRpcTimeoutDuration(Duration.ofMillis(60000L))
.setTotalTimeoutDuration(Duration.ofMillis(60000L))
.build();
RPC 嘗試是指個別嘗試,而 RPC 作業則是指所有嘗試的集合。單一 RPC 呼叫會在單一作業中嘗試一或多次。
個別 RPC 範圍 (嘗試) 由下列設定控管:
setInitialRetryDelayDuration: 第一次嘗試前的延遲時間。setRetryDelayMultiplier:每次嘗試之間的延遲乘數。setMaxRetryDelayDuration:嘗試作業可能出現的最大延遲時間。setInitialRpcTimeoutDuration:第一次嘗試的逾時時間。setRpcTimeoutMultiplier:每次嘗試之間套用的逾時乘數。setMaxRpcTimeoutDuration: 嘗試的逾時時間上限。
總 RPC 範圍 (作業) 由下列設定控管:
setTotalTimeout: 整個作業允許的總逾時時間。setMaxAttempts: 允許的嘗試次數上限。
重試 RPC 時
發生下列兩種情況時,系統會重試 RPC:
- 程式庫收到非成功的狀態碼,且狀態碼標示為可重試。
- RPC 呼叫超出個別 RPC 範圍,但仍落在 RPC 總範圍內。
如果只有一個情境為 True,或兩個情境皆為 False,則系統不會重試 RPC。
舉例來說,如果尚未超過總逾時時間,但最新嘗試收到無法重試的狀態碼。
此外,設定 RPC 範圍時,您可以設定每次嘗試的範圍,以及 RPC 總範圍。重試演算法會確保個別嘗試的界限落在 RPC 總界限內。
指數輪詢
指數輪詢會重試要求,並增加每次重試嘗試之間的延遲時間。這個重試延遲值可設為重試延遲值上限。
舉例來說,下列重試設定可能會導致以下延遲時間:
Initial Retry Delay: 100ms
Retry Delay Multiplier: 2.0
Max Retry Delay: 500ms
- 嘗試 1:延遲 100 毫秒
- 嘗試 2:延遲 200 毫秒
- 嘗試 3:延遲 400 毫秒
- 嘗試 4:延遲 500 毫秒
- ...
- 嘗試 X:延遲 500 毫秒
時基誤差
抖動是使用隨機性新增的變異數,可分散 RPC 的叫用時間。 Google Cloud 用戶端程式庫一律會為重試啟用抖動。這有助於分散重試次數,避免伺服器負載過重。
系統會根據重試延遲計算隨機抖動值。每次嘗試前,重試演算法都會計算介於 [1, RETRY_DELAY] 之間的隨機值。這個計算值是要求傳送至伺服器前的約略延遲時間。
下列重試設定會使用抖動和指數輪詢。
Initial Retry Delay: 100ms
Retry Delay Multiplier: 2.0
Max Retry Delay: 500ms
這可能會導致下列延遲時間:
- 嘗試 1:延遲介於
[1, 100]毫秒之間的隨機值 - 嘗試 2:延遲介於
[1, 200]毫秒之間的隨機值 - 嘗試 3:延遲介於
[1, 400]毫秒之間的隨機值 - 嘗試 4:延遲介於
[1, 500]毫秒之間的隨機值 - ...
- 嘗試 X:延遲介於
[1, 500]毫秒之間的隨機值
重試範例
以下範例說明部分重試設定的行為。
不重試
這個範例會停用重試功能。
RetrySettings defaultNoRetrySettings =
RetrySettings.newBuilder()
// Use the default configurations for other settings
.setTotalTimeoutDuration(Duration.ofMillis(5000L))
// Explicitly set retries as disabled (maxAttempts == 1)
.setMaxAttempts(1)
.build();
或者,您也可以使用下列範例設定這項行為:
RetrySettings defaultNoRetrySettings =
RetrySettings.newBuilder()
.setLogicalTimeoutDuration(Duration.ofMillis(5000L))
.build();
下表顯示嘗試次數:
| 嘗試次數 | 遠端程序呼叫 (RPC) 逾時 | 重試延遲 | 通話已發起 | 通話結束 |
|---|---|---|---|---|
| 1 | 5000 毫秒 | 0 毫秒 | 0 毫秒 | 5000 毫秒 |
重試範例
這個範例會啟用重試功能,並指定延遲時間和逾時時間。
RetrySettings.newBuilder()
.setInitialRetryDelayDuration(Duration.ofMillis(200L))
.setRetryDelayMultiplier(2.0)
.setMaxRetryDelayDuration(Duration.ofMillis(500L))
.setInitialRpcTimeoutDuration(Duration.ofMillis(1500L))
.setRpcTimeoutMultiplier(2.0)
.setMaxRpcTimeoutDuration(Duration.ofMillis(3000L))
.setTotalTimeoutDuration(Duration.ofMillis(5000L))
.build();
下表顯示嘗試次數:
| 嘗試次數 | 遠端程序呼叫 (RPC) 逾時 | 重試延遲 | 通話已發起 | 通話結束 |
|---|---|---|---|---|
| 1 | 1500 毫秒 | 0 毫秒 | 0 毫秒 | 1500 毫秒 |
| 2 (重試) | 3000 毫秒 | 200 毫秒 | 1700 毫秒 | 4700ms |
| 3 (未嘗試重試) | - | 400 毫秒 | - | - |
重試範例:總逾時時間較長
這個範例與第一個重試範例類似,但總逾時時間較長,可展示額外的重試嘗試,以及最後一次重試嘗試的 RPC 逾時上限。
RetrySettings.newBuilder()
.setInitialRetryDelayDuration(Duration.ofMillis(200L))
.setRetryDelayMultiplier(2.0)
.setMaxRetryDelayDuration(Duration.ofMillis(500L))
.setInitialRpcTimeoutDuration(Duration.ofMillis(1500L))
.setRpcTimeoutMultiplier(2.0)
.setMaxRpcTimeoutDuration(Duration.ofMillis(3000L))
.setTotalTimeoutDuration(Duration.ofMillis(10000L))
.build();
下表顯示嘗試次數:
| 嘗試次數 | 遠端程序呼叫 (RPC) 逾時 | 重試延遲 | 通話已發起 | 通話結束 |
|---|---|---|---|---|
| 1 | 1500 毫秒 | 0 毫秒 | 0 毫秒 | 1500 毫秒 |
| 2 (重試) | 3000 毫秒 | 200 毫秒 | 1700 毫秒 | 4700ms |
| 3 (重試) | 4900 毫秒 | 400 毫秒 | 5100 毫秒 | 10000 毫秒 |
由於「總逾時」值,第三次重試的 RPC 逾時值受到限制。 將乘數 (2.0) 乘以先前的逾時值 (3000 毫秒),即可得出 6000 毫秒的 RPC 逾時。不過,RPC 逾時時間不得超過總逾時時間,且會縮減為「剩餘時間」(10000 - 5100 = 4900)。
重試範例:RPC 逾時上限
RetrySettings defaultRetrySettings =
RetrySettings.newBuilder()
.setInitialRetryDelayDuration(Duration.ofMillis(200L))
.setRetryDelayMultiplier(2.0)
.setMaxRetryDelayDuration(Duration.ofMillis(500L))
.setInitialRpcTimeoutDuration(Duration.ofMillis(500L))
.setRpcTimeoutMultiplier(2.0)
.setMaxRpcTimeoutDuration(Duration.ofMillis(2000L))
.setTotalTimeoutDuration(Duration.ofMillis(4000L))
.build();
下表顯示嘗試次數:
| 嘗試次數 | 遠端程序呼叫 (RPC) 逾時 | 重試延遲 | 通話已發起 | 通話結束 |
|---|---|---|---|---|
| 1 | 500 毫秒 | 0 毫秒 | 0 毫秒 | 500 毫秒 |
| 2 (重試) | 1000 毫秒 | 200 毫秒 | 700 毫秒 | 1700 毫秒 |
| 3 (Retry) | 1900 毫秒 | 400 毫秒 | 2100 毫秒 | 4000 毫秒 |
另一個例子:RPC 超時上限不得超過總超時。
如何為 RPC 設定自訂重試參數
以下範例使用 Java-Asset 用戶端程式庫:
使用自訂設定建立
RetrySettings類別:RetrySettings customRetrySettings = RetrySettings.newBuilder() // ... Retry Configurations .build(); RetrySettings customRetrySettings2 = RetrySettings.newBuilder() // ... Retry Configurations .build();為用戶端建立
StubSettings.Builder,並為 RPC 設定:AssetServiceStubSettings.Builder assetStubSettingsBuilder = AssetServiceStubSettings.newBuilder(); assetStubSettingsBuilder .exportAssetsSettings() // Set your custom Retry Settings .setRetrySettings(customRetrySettings) // Set your custom Retryable Codes .setRetryableCodes(ImmutableSet.of(StatusCode.Code.DEADLINE_EXCEEDED));提供的程式碼片段會為
AssetServiceClient的ExportAssetsRPC 設定自訂重試設定。這會將ExportAssetsRPC 設定為使用customRetrySettings中設定的重試設定,並將可重試的程式碼設為DEADLINE_EXCEEDED。建立用戶端設定,如
assetSettings:java AssetServiceSettings assetSettings = AssetServiceSettings.create(assetStubSettingsBuilder.build());4. 使用設定建立用戶端,如assetClient。java try (AssetServiceClient assetClient = AssetServiceClient.create(assetSettings)) { ... }
針對要設定的每個 RPC 重複執行步驟 2。例如:
AssetServiceStubSettings.Builder assetStubSettingsBuilder = AssetServiceStubSettings.newBuilder();
// Modify the retry params for ExportAssets RPC
assetStubSettingsBuilder
.exportAssetsSettings()
.setRetrySettings(customRetrySettings)
.setRetryableCodes(ImmutableSet.of(StatusCode.Code.DEADLINE_EXCEEDED));
// Modify the retry params for ListAssets RPC
assetStubSettingsBuilder
.listAssetsSettings()
.setRetrySettings(customRetrySettings2)
.setRetryableCodes(ImmutableSet.of(StatusCode.Code.UNAVAILABLE));
常見問題
以下是關於用戶端重試行為的常見問題。
我預期會重試 X 次,但實際重試了 Y 次。
除非您明確指定嘗試次數上限 (並停用逾時設定),否則您看到的重試次數可能不一致。RPC 延遲的隨機值會產生抖動,因此難以預測要求實際傳送的時間。
RPC 在達到「總逾時」值之前傳回失敗。
重試演算法會在每次重試時計算重試延遲值。系統會排定在未來 (即 currentTime() + jitteredRetryDelay) 執行計算出的重試延遲時間。如果排定的嘗試時間超過總逾時時間,系統就不會進行最後一次重試。
我設定了自訂設定,但遇到配額問題。
您可能將 RetrySettings 設為過於積極地執行。服務營運團隊會選擇預設的重試值。
請考慮增加重試延遲時間 (初始重試延遲時間和重試乘數),讓重試作業間隔更長,頻率更低。請注意,這可能會導致回覆速度較慢。
您的用途可能需要更快速的回應或更頻繁的重試次數,或兩者皆是。如果是這樣,請嘗試提高配額限制。