Les bibliothèques clientes Cloud pour Java utilisent des nouvelles tentatives pour gérer les échecs transitoires inattendus (c'est-à-dire lorsque le serveur est temporairement indisponible). Plusieurs tentatives peuvent aboutir à une réponse positive du serveur.
Les valeurs de tentatives par défaut sont sélectionnées par l'équipe qui gère le service cloud. Ces valeurs de nouvelle tentative sont configurées par RPC. Un service peut choisir de n'activer les nouvelles tentatives que pour un sous-ensemble de RPC. Il est possible que chaque RPC d'un service soit configuré différemment.
Paramètres de nouvelle tentative
Les bibliothèques clientes comportent deux types de paramètres de nouvelle tentative à configurer :
- Code d'état de nouvelle tentative : ensemble de codes d'état sur lesquels effectuer une nouvelle tentative.
- Délai avant nouvelle tentative ou limites de tentatives : RetrySettings configurable pour définir les limites.
Emplacement de la configuration par défaut des nouvelles tentatives RPC
Les configurations de réessai par défaut sont définies dans le fichier {Client}StubSettings généré. En utilisant l'RPC ExportAssets dans Java-Asset v3.64.0 comme exemple, les configurations de réessai par défaut sont définies aux emplacements suivants :
Codes d'état des nouvelles tentatives : configurés dans le fichier
AssetServiceStubSettings.java. Exemple :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();Paramètres de nouvelle tentative : configurés dans le fichier
AssetServiceStubSettings.java. Exemple :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();
Les deux configurations sont mappées au RPC dans le fichier AssetServiceStubSettings.java. Exemple :
builder
.exportAssetsSettings()
.setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("no_retry_0_codes"))
.setRetrySettings(RETRY_PARAM_DEFINITIONS.get("no_retry_0_params"));
Concepts de réessai des bibliothèques clientes
L'activation des nouvelles tentatives permet à un RPC d'effectuer plusieurs tentatives pour réussir un appel. Un appel réussi est une réponse d'un serveur qui renvoie un code d'état OK (à partir de gRPC) ou un code d'état 2xx (à partir de HttpJson).
Tentative ou opération
La configuration RetrySettings suivante modifie les paramètres de nouvelle tentative pour une tentative et une opération 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();
Une tentative RPC est une tentative individuelle, tandis qu'une opération RPC est un ensemble de toutes les tentatives effectuées. Une seule invocation RPC comportera une ou plusieurs tentatives dans une même opération.
Les limites RPC individuelles (tentative) sont contrôlées par les paramètres suivants :
setInitialRetryDelayDuration: Délai avant la première tentative.setRetryDelayMultiplier: Multiplicateur de délai appliqué entre chaque tentative.setMaxRetryDelayDuration: délai maximal possible pour une tentative.setInitialRpcTimeoutDuration: Délai d'expiration pour la première tentative.setRpcTimeoutMultiplier: Multiplicateur de délai d'inactivité appliqué entre chaque tentative.setMaxRpcTimeoutDuration: délai d'attente maximal possible pour une tentative.
Les limites totales de RPC (une opération) sont contrôlées par les paramètres suivants :
setTotalTimeout: délai total autorisé pour l'ensemble de l'opération.setMaxAttempts: nombre maximal de tentatives autorisées.
Lorsqu'un RPC est relancé
Une nouvelle tentative de RPC est effectuée lorsque les deux scénarios suivants se produisent :
- La bibliothèque reçoit un code d'état non réussi et le code d'état est marqué comme pouvant être réessayé.
- Une invocation RPC dépasse les limites RPC individuelles, mais reste dans les limites RPC totales.
Si un seul scénario est vrai ou si aucun ne l'est, la RPC ne sera pas relancée.
Par exemple, si le délai d'attente total n'a pas été dépassé, mais que la dernière tentative reçoit un code d'état qui ne peut pas être réessayé.
De plus, lorsque vous configurez les limites RPC, vous pouvez configurer les limites pour chaque tentative ainsi que les limites RPC totales. L'algorithme de réessai garantit que les limites d'une tentative individuelle se situent dans les limites du RPC total.
Intervalle exponentiel entre les tentatives
L'intervalle exponentiel entre les tentatives relance les requêtes avec un délai croissant entre chaque nouvelle tentative. Cette valeur de délai avant nouvelle tentative peut être plafonnée avec une valeur maximale de délai avant nouvelle tentative.
Par exemple, les configurations de nouvelle tentative suivantes peuvent entraîner les délais suivants :
Initial Retry Delay: 100ms
Retry Delay Multiplier: 2.0
Max Retry Delay: 500ms
- Tentative 1 : délai de 100 ms
- Tentative 2 : délai de 200 ms
- Tentative 3 : délai de 400 ms
- Tentative 4 : délai de 500 ms
- …
- Tentative X : délai de 500 ms
Gigue
La gigue est une variance ajoutée qui utilise l'aléatoire pour répartir le moment où les RPC sont appelés. Google Cloud Les bibliothèques clientes activent toujours la gigue pour les nouvelles tentatives. Cela permet d'étaler les tentatives sans surcharger le serveur.
La valeur aléatoire de jitter est calculée en fonction du délai avant nouvelle tentative. Avant chaque tentative, l'algorithme de réessai calcule une valeur aléatoire comprise entre [1, RETRY_DELAY]. Cette valeur calculée correspond au délai approximatif avant que la requête ne soit envoyée au serveur.
Les configurations de nouvelle tentative suivantes utilisent la gigue et l'intervalle exponentiel entre les tentatives.
Initial Retry Delay: 100ms
Retry Delay Multiplier: 2.0
Max Retry Delay: 500ms
Voici les délais de traitement possibles :
- Tentative 1 : délai d'une valeur aléatoire comprise entre
[1, 100]ms - Tentative 2 : délai d'une valeur aléatoire comprise entre
[1, 200]ms - Troisième tentative : retarder une valeur aléatoire entre
[1, 400]ms - Quatrième tentative : retarder une valeur aléatoire entre
[1, 500]ms - …
- Tentative X : délai d'une valeur aléatoire comprise entre
[1, 500]ms
Exemples de nouvelles tentatives
Les exemples suivants illustrent le comportement de certaines configurations de réessai.
Pas de nouvelle tentative
Cet exemple désactive les nouvelles tentatives.
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();
Vous pouvez également configurer ce comportement avec l'exemple suivant :
RetrySettings defaultNoRetrySettings =
RetrySettings.newBuilder()
.setLogicalTimeoutDuration(Duration.ofMillis(5000L))
.build();
Le tableau suivant présente les tentatives :
| Numéro de la tentative | Délai RPC avant expiration | Délai d'intervalle | Appel invoqué | Appel terminé |
|---|---|---|---|---|
| 1 | 5000ms | 0 ms | 0 ms | 5000ms |
Exemple de nouvelle tentative
Cet exemple active les nouvelles tentatives avec des délais et des délais d'attente spécifiés.
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();
Le tableau suivant présente les tentatives :
| Numéro de la tentative | Délai RPC avant expiration | Délai d'intervalle | Appel invoqué | Appel terminé |
|---|---|---|---|---|
| 1 | 1 500 ms | 0 ms | 0 ms | 1 500 ms |
| 2 (Réessayer) | 3000ms | 200ms | 1700 ms | 4700ms |
| 3 (Nouvelle tentative non effectuée) | - | 400ms | - | - |
Exemple de nouvelle tentative : délai total plus long
Cet exemple est semblable au premier exemple de nouvelle tentative, mais il présente un délai avant expiration total plus long pour illustrer une tentative supplémentaire et le délai avant expiration RPC limité pour la dernière tentative.
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();
Le tableau suivant présente les tentatives :
| Numéro de la tentative | Délai RPC avant expiration | Délai d'intervalle | Appel invoqué | Appel terminé |
|---|---|---|---|---|
| 1 | 1 500 ms | 0 ms | 0 ms | 1 500 ms |
| 2 (Réessayer) | 3000ms | 200ms | 1700 ms | 4700ms |
| 3 (Réessayer) | 4900ms | 400ms | 5100 ms | 10000ms |
La valeur du délai RPC de la troisième tentative est limitée par la valeur du délai total. Si vous utilisez le multiplicateur (2.0) avec la valeur de délai avant expiration précédente (3 000 ms), le délai avant expiration RPC sera de 6 000 ms. Toutefois, le délai RPC ne doit pas dépasser le délai total. Il est réduit pour correspondre au "temps restant" (10 000 – 5 100 = 4 900).
Exemple de nouvelle tentative : délai RPC limité
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();
Le tableau suivant présente les tentatives :
| Numéro de la tentative | Délai RPC avant expiration | Délai d'intervalle | Appel invoqué | Appel terminé |
|---|---|---|---|---|
| 1 | 500ms | 0 ms | 0 ms | 500ms |
| 2 (Réessayer) | 1000ms | 200ms | 700 ms | 1700 ms |
| 3 (Réessayer) | 1900ms | 400ms | 2 100 ms | 4000ms |
Autre exemple où le délai avant expiration du RPC est plafonné pour ne pas dépasser le délai avant expiration total.
Configurer des paramètres de nouvelle tentative personnalisés pour un RPC
L'exemple suivant utilise la bibliothèque cliente Java-Asset :
Créez la classe
RetrySettingsavec vos configurations personnalisées :RetrySettings customRetrySettings = RetrySettings.newBuilder() // ... Retry Configurations .build(); RetrySettings customRetrySettings2 = RetrySettings.newBuilder() // ... Retry Configurations .build();Créez le
StubSettings.Builderpour votre client et configurez-le pour le 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));L'extrait de code fourni définit des configurations de nouvelle tentative personnalisées pour le RPC
ExportAssetsdeAssetServiceClient. Il configure le RPCExportAssetspour qu'il utilise les paramètres de nouvelle tentative configurés danscustomRetrySettingset définit les codes pouvant faire l'objet d'une nouvelle tentative surDEADLINE_EXCEEDED.Créez les paramètres du client en tant que
assetSettings:java AssetServiceSettings assetSettings = AssetServiceSettings.create(assetStubSettingsBuilder.build());4.Créez le client avec les paramètres en tant queassetClient.java try (AssetServiceClient assetClient = AssetServiceClient.create(assetSettings)) { ... }
Répétez l'étape 2 pour chaque RPC que vous souhaitez configurer. Exemple :
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));
Questions fréquentes
Vous trouverez ci-dessous les questions fréquemment posées concernant le comportement de réessai des clients.
Je m'attendais à X tentatives, mais il y en a eu Y.
À moins que vous ne spécifiiez explicitement le nombre maximal de tentatives (en plus de désactiver les configurations de délai avant expiration), vous ne verrez peut-être pas toujours le même nombre de tentatives de réessai. Les valeurs aléatoires de gigue pour le délai RPC rendent difficile la prédiction du moment où la requête est réellement envoyée.
Le RPC a renvoyé un échec avant que la valeur du délai total ne soit atteinte.
L'algorithme de nouvelle tentative calcule la valeur du délai de nouvelle tentative avec gigue à chaque tentative. Le délai de nouvelle tentative calculé sera planifié pour une exécution ultérieure (c'est-à-dire currentTime() + jitteredRetryDelay). Si l'heure de la tentative planifiée dépasse le délai total, la dernière tentative ne sera pas effectuée.
J'ai configuré des paramètres personnalisés et je rencontre des problèmes de quota.
Il est possible que vous ayez configuré RetrySettings pour qu'il s'exécute de manière trop agressive. Les valeurs de nouvelle tentative par défaut sont choisies par l'équipe qui gère le service.
Envisagez d'augmenter le délai entre les tentatives (délai initial et multiplicateur) pour que les tentatives soient plus espacées et moins fréquentes. Notez que cela peut entraîner un délai de réponse plus long.
Votre cas d'utilisation peut nécessiter une réponse plus rapide ou des tentatives plus fréquentes, ou les deux. Dans ce cas, essayez d'augmenter les limites de quota.