Las APIs deGoogle Cloud usan operaciones de larga duración (LRO) para las llamadas que se espera que tarden un tiempo significativo en completarse (por ejemplo, aprovisionar una instancia de Compute Engine o inicializar una canalización de Dataflow).
Estas APIs no mantienen una conexión activa de larga duración ni se bloquean mientras se ejecuta la tarea. En el caso de las APIs de LRO, las bibliotecas cliente de Cloud para Java devuelven un future para que lo verifiques más adelante.
Cómo determinar si una API es un LRO
Existen dos formas principales de determinar si una API es un LRO:
- Las APIs de LRO tienen el sufijo
Async(por ejemplo,createClusterAsync) oOperationCallable(por ejemplo,createClusterOperationCallable). - Las APIs de LRO devuelven un
OperationFutureo unOperationCallable.
En el siguiente fragmento, se muestran las dos variaciones, con Java-Dataproc como ejemplo:
// Async suffix (#1) returns OperationFuture (#2)
public final OperationFuture<Cluster, ClusterOperationMetadata> createClusterAsync(CreateClusterRequest request)
// OperationCallable suffix (#1) returns OperationCallable (#2)
public final OperationCallable<CreateClusterRequest, Cluster, ClusterOperationMetadata> createClusterOperationCallable()
Estas son dos variaciones de la misma API y no dos APIs diferentes (ambas llamadas crean un clúster de Dataproc). Se recomienda la variante Async.
Flujo general de una LRO
Las APIs de LRO son, básicamente, una llamada de solicitud inicial seguida de una serie de llamadas de sondeo pequeñas. La llamada inicial envía la solicitud y crea una "operación" en el servidor. Todas las llamadas de sondeo posteriores al servidor hacen un seguimiento del estado de la operación. Si la operación finalizó, se devuelve la respuesta. De lo contrario, se devuelve un estado incompleto y la biblioteca cliente determina si debe volver a sondear.
De forma predeterminada, el cliente controla la lógica de sondeo, y no es necesario que configures el mecanismo de sondeo, a menos que tengas requisitos específicos.
Desde tu perspectiva, la llamada se ejecuta en segundo plano hasta que se recibe una respuesta. Las llamadas de sondeo y las configuraciones de tiempo de espera tienen valores predeterminados que el equipo de servicio preconfigura según el tiempo esperado para sus APIs. Estas configuraciones controlan muchos factores, como la frecuencia con la que se debe sondear y el tiempo que se debe esperar antes de abandonar.
Las bibliotecas cliente de Cloud para Java proporcionan una interfaz para interactuar con el LRO a través de OperationFuture.
En el siguiente fragmento, se muestra cómo llamar a una operación y esperar una respuesta con Java-Dataproc como ejemplo:
try (ClusterControllerClient clusterControllerClient = ClusterControllerClient.create()) {
CreateClusterRequest request =
CreateClusterRequest.newBuilder().build();
OperationFuture<Cluster, ClusterOperationMetadata> future =
clusterControllerClient.createClusterAsync(request);
// Blocks until there is a response
Cluster response = future.get();
} catch (CancellationException e) {
// Exceeded the timeout without the Operation completing.
// Library is no longer polling for the Operation's status.
}
Valores predeterminados de LRO
Puedes encontrar los valores predeterminados en la clase StubSettings de cada cliente. El método initDefaults() inicializa la configuración del LRO dentro de la clase Builder anidada.
Por ejemplo, en Java-Aiplatform v3.24.0, la llamada a la LRO de deployModel tiene los siguientes parámetros predeterminados:
OperationTimedPollAlgorithm.create(
RetrySettings.newBuilder()
.setInitialRetryDelayDuration(Duration.ofMillis(5000L))
.setRetryDelayMultiplier(1.5)
.setMaxRetryDelayDuration(Duration.ofMillis(45000L))
.setTotalTimeoutDuration(Duration.ofMillis(300000L))
.setInitialRpcTimeoutDuration(Duration.ZERO) // not used
.setRpcTimeoutMultiplier(1.0) // not used
.setMaxRpcTimeoutDuration(Duration.ZERO) // not used
.build()));
Tanto los reintentos como los LRO comparten la misma clase RetrySettings. En la siguiente tabla, se muestra la asignación entre los campos dentro de RetrySettings y la funcionalidad del LRO:
| RetrySettings | Descripción |
|---|---|
| InitialRetryDelay | Es la demora inicial antes de la primera votación. |
| MaxRetryDelay | Es la demora máxima entre cada sondeo. |
| RetryDelayMultiplier | Es el multiplicador para la demora del reintento de sondeo entre sondeos. |
| TotalTimeoutDuration | Es el tiempo máximo permitido para la operación de larga duración. |
Cuándo configurar los valores de LRO
El principal caso de uso para configurar manualmente los valores de LRO es modificar las frecuencias de sondeo debido a los tiempos de espera de LRO. Si bien los valores predeterminados se configuran como una estimación del equipo de servicio, ciertos factores pueden provocar tiempos de espera ocasionales.
Para reducir la cantidad de tiempos de espera agotados, aumenta el valor del tiempo de espera total. Aumentar los otros valores también puede ayudar, y debes probarlos para garantizar el comportamiento esperado.
Cómo configurar los valores de LRO
Para configurar los valores del LRO, crea un objeto OperationTimedPollAlgorithm y actualiza el algoritmo de sondeo para un LRO específico. En el siguiente fragmento, se usa Java-Dataproc como ejemplo:
ClusterControllerSettings.Builder settingsBuilder = ClusterControllerSettings.newBuilder();
// Create a new OperationTimedPollAlgorithm object
TimedRetryAlgorithm timedRetryAlgorithm = OperationTimedPollAlgorithm.create(
RetrySettings.newBuilder()
.setInitialRetryDelayDuration(Duration.ofMillis(500L))
.setRetryDelayMultiplier(1.5)
.setMaxRetryDelayDuration(Duration.ofMillis(5000L))
.setTotalTimeoutDuration(Duration.ofHours(24L))
.build());
// Set the new polling settings for the specific LRO API
settingsBuilder.createClusterOperationSettings().setPollingAlgorithm(timedRetryAlgorithm);
ClusterControllerClient clusterControllerClient = ClusterControllerClient.create(settingsBuilder.build());
Esta configuración solo modifica los valores del LRO para la RPC de createClusterOperation. Los otros RPCs del cliente seguirán usando los valores de LRO preconfigurados para cada RPC, a menos que también se modifiquen.
Tiempos de espera de LRO
La biblioteca sigue sondeando mientras no se supere el tiempo de espera total. Si se excedió el tiempo de espera total, la biblioteca arroja un java.util.concurrent.CancellationException con el mensaje "Se canceló la tarea".
Un CancellationException no significa que se haya cancelado la tarea de backend Google Cloud. Esta excepción se arroja desde la biblioteca cliente cuando una llamada superó el tiempo de espera total y no recibió una respuesta. Incluso si la tarea se completa inmediatamente después del tiempo de espera, la biblioteca cliente no verá la respuesta.