Gestione delle operazioni a lunga esecuzione

Le APIGoogle Cloud utilizzano operazioni di lunga durata (LRO) per le chiamate che dovrebbero richiedere un tempo significativo per essere completate (ad esempio, il provisioning di un'istanza Compute Engine o l'inizializzazione di una pipeline Dataflow). Queste API non mantengono una connessione attiva a lunga durata né bloccano l'esecuzione dell'attività. Per le API LRO, le librerie client di Cloud per Java restituiscono un future da controllare in un secondo momento.

Determinare se un'API è un'operazione di lunga durata

Esistono due modi principali per determinare se un'API è un'operazione di lunga durata:

  • Le API LRO hanno il suffisso Async (ad esempio, createClusterAsync) o OperationCallable (ad esempio, createClusterOperationCallable).
  • Le API LRO restituiscono OperationFuture o OperationCallable.

Il seguente snippet mostra le due varianti, utilizzando Java-Dataproc come esempio:

// 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()

Si tratta di due varianti della stessa API e non di due API diverse (entrambe le chiamate creano un cluster Dataproc). È consigliata la variante Async.

Flusso di alto livello di un LRO

Le API LRO sono essenzialmente una chiamata di richiesta iniziale seguita da una serie di piccole chiamate di polling. La chiamata iniziale invia la richiesta e crea un'"operazione" sul server. Tutte le successive chiamate di polling al server monitorano lo stato dell'operazione. Se l'operazione è terminata, viene restituita la risposta. In caso contrario, viene restituito uno stato incompleto e la libreria client determina se eseguire nuovamente il polling.

Per impostazione predefinita, il client gestisce la logica di polling e non è necessario configurare il meccanismo di polling, a meno che tu non abbia requisiti specifici.

Dal tuo punto di vista, la chiamata viene eseguita in background finché non viene ricevuta una risposta. Le chiamate di polling e le configurazioni del timeout hanno valori predefiniti preconfigurati dal team del servizio in base al tempo previsto per le API. Queste configurazioni controllano molti fattori, ad esempio la frequenza di polling e il tempo di attesa prima di rinunciare.

Le librerie client di Cloud per Java forniscono un'interfaccia per interagire con l'operazione di lunga durata utilizzando OperationFuture.

Il seguente snippet mostra come chiamare un'operazione e attendere una risposta, utilizzando Java-Dataproc come esempio:

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.
}

Valori LRO predefiniti

Puoi trovare i valori predefiniti all'interno della classe StubSettings di ogni cliente. Il metodo initDefaults() inizializza le impostazioni LRO all'interno della classe Builder nidificata.

Ad esempio, in Java-Aiplatform v3.24.0, la chiamata LRO deployModel ha i seguenti parametri predefiniti:

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()));

I tentativi e le LRO condividono la stessa classe RetrySettings. La seguente tabella mostra la mappatura tra i campi all'interno di RetrySettings e la funzionalità LRO:

RetrySettings Descrizione
InitialRetryDelay Ritardo iniziale prima del primo sondaggio.
MaxRetryDelay Ritardo massimo tra ogni polling.
RetryDelayMultiplier Moltiplicatore per il ritardo tra i tentativi di sondaggio.
TotalTimeoutDuration Tempo massimo consentito per l'operazione a lunga esecuzione.

Quando configurare i valori LRO

Il principale caso d'uso per configurare manualmente i valori LRO è la modifica delle frequenze di polling a causa dei timeout LRO. Sebbene i valori predefiniti siano configurati come stima dal team del servizio, alcuni fattori potrebbero causare occasionalmente timeout.

Per ridurre il numero di timeout, aumenta il valore totale del timeout. Anche l'aumento degli altri valori può essere utile e devi testarli per assicurarti il comportamento previsto.

Come configurare i valori LRO

Per configurare i valori LRO, crea un oggetto OperationTimedPollAlgorithm e aggiorna l'algoritmo di polling per un LRO specifico. Lo snippet seguente utilizza Java-Dataproc come esempio:

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());

Questa configurazione modifica solo i valori LRO per la RPC createClusterOperation. Le altre RPC nel client utilizzano ancora i valori LRO preconfigurati per ogni RPC, a meno che non vengano modificati.

Timeout LRO

La libreria continua a eseguire il polling finché il timeout totale non è stato superato. Se il timeout totale è stato superato, la libreria genera un'eccezione java.util.concurrent.CancellationException con il messaggio "Task was cancelled" (Attività annullata).

Un CancellationException non significa che l'attività Google Cloud di backend è stata annullata. Questa eccezione viene generata dalla libreria client quando una chiamata ha superato il timeout totale e non ha ricevuto una risposta. Anche se l'attività viene completata immediatamente dopo il timeout, la risposta non verrà visualizzata dalla libreria client.