Vorgänge mit langer Ausführungszeit verwalten

Google Cloud APIs verwenden Vorgänge mit langer Ausführungszeit (long-running operations, LROs) für Aufrufe, die voraussichtlich längere Zeit in Anspruch nehmen (z. B. das Bereitstellen einer Compute Engine-Instanz oder das Initialisieren einer Dataflow-Pipeline). Diese APIs halten keine aktive, langlebige Verbindung aufrecht und blockieren nicht, während die Aufgabe ausgeführt wird. Bei LRO-APIs geben die Cloud-Clientbibliotheken für Java ein future zurück, das Sie später prüfen können.

Ermitteln, ob eine API ein LRO ist

Es gibt zwei Möglichkeiten, um festzustellen, ob eine API ein LRO ist:

  • LRO-APIs haben entweder das Suffix Async (z. B. createClusterAsync) oder OperationCallable (z. B. createClusterOperationCallable).
  • LRO-APIs geben entweder OperationFuture oder OperationCallable zurück.

Das folgende Snippet zeigt die beiden Varianten am Beispiel von Java-Dataproc:

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

Dies sind zwei Varianten für dieselbe API und nicht zwei verschiedene APIs (mit beiden Aufrufen wird ein Dataproc-Cluster erstellt). Die Variante Async wird empfohlen.

Allgemeiner Ablauf eines LRO

LRO-APIs bestehen im Wesentlichen aus einem ersten Anforderungsaufruf, gefolgt von einer Reihe kleiner Abfrageaufrufe. Beim ersten Aufruf wird die Anfrage gesendet und ein Vorgang auf dem Server erstellt. Bei allen nachfolgenden Abfrageaufrufen an den Server wird der Status des Vorgangs verfolgt. Wenn der Vorgang abgeschlossen ist, wird die Antwort zurückgegeben. Andernfalls wird ein unvollständiger Status zurückgegeben und die Clientbibliothek entscheidet, ob noch einmal abgefragt werden soll.

Standardmäßig übernimmt der Client die Polling-Logik. Sie müssen den Polling-Mechanismus nur konfigurieren, wenn Sie spezielle Anforderungen haben.

Aus Ihrer Sicht läuft der Anruf im Hintergrund, bis eine Antwort eingeht. Die Polling-Aufrufe und Timeout-Konfigurationen haben Standardwerte, die vom Serviceteam basierend auf der erwarteten Zeit für die APIs vorkonfiguriert werden. Diese Konfigurationen steuern viele Faktoren, z. B. wie oft abgefragt wird und wie lange gewartet wird, bevor aufgegeben wird.

Die Cloud-Clientbibliotheken für Java bieten eine Schnittstelle für die Interaktion mit dem LRO über OperationFuture.

Das folgende Snippet zeigt, wie ein Vorgang aufgerufen und auf eine Antwort gewartet wird. Als Beispiel wird Java-Dataproc verwendet:

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

Standardwerte für LROs

Die Standardwerte finden Sie in der StubSettings-Klasse des jeweiligen Clients. Die Methode initDefaults() initialisiert die LRO-Einstellungen in der verschachtelten Klasse Builder.

Im Java-Aiplatform v3.24.0-Beispiel hat der deployModel-LRO-Aufruf die folgenden Standardparameter:

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

Sowohl Wiederholungsversuche als auch LROs verwenden dieselbe RetrySettings-Klasse. In der folgenden Tabelle sehen Sie die Zuordnung zwischen den Feldern in RetrySettings und der LRO-Funktionalität:

RetrySettings Beschreibung
InitialRetryDelay Anfängliche Verzögerung vor dem ersten Poll.
MaxRetryDelay Maximale Verzögerung zwischen den einzelnen Abfragen.
RetryDelayMultiplier Multiplikator für die Verzögerung bei Wiederholungsversuchen zwischen Abfragen.
TotalTimeoutDuration Maximal zulässige Zeit für den Vorgang mit langer Ausführungszeit.

Wann LRO-Werte konfiguriert werden sollten

Der Hauptanwendungsfall für die manuelle Konfiguration der LRO-Werte ist die Änderung der Polling-Häufigkeit aufgrund von LRO-Timeouts. Die Standardwerte werden vom Serviceteam als Schätzung konfiguriert. Bestimmte Faktoren können jedoch zu gelegentlichen Zeitüberschreitungen führen.

Erhöhen Sie den Gesamtwert für das Zeitlimit, um die Anzahl der Zeitüberschreitungen zu reduzieren. Auch das Erhöhen der anderen Werte kann helfen. Sie sollten sie testen, um das erwartete Verhalten zu erzielen.

LRO-Werte konfigurieren

Um die LRO-Werte zu konfigurieren, erstellen Sie ein OperationTimedPollAlgorithm-Objekt und aktualisieren Sie den Polling-Algorithmus für eine bestimmte LRO. Im folgenden Snippet wird Java-Dataproc als Beispiel verwendet:

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

Mit dieser Konfiguration werden nur die LRO-Werte für den createClusterOperation-RPC geändert. Die anderen RPCs im Client verwenden weiterhin die vorkonfigurierten LRO-Werte für jeden RPC, sofern sie nicht auch geändert werden.

LRO-Auszeiten

Die Bibliothek fragt so lange ab, bis das gesamte Zeitlimit überschritten wurde. Wenn das gesamte Zeitlimit überschritten wurde, löst die Bibliothek eine java.util.concurrent.CancellationException mit der Meldung „Task was cancelled.“ aus.

Ein CancellationException bedeutet nicht, dass die Backend-Aufgabe Google Cloudabgebrochen wurde. Diese Ausnahme wird von der Clientbibliothek ausgelöst, wenn ein Aufruf das gesamte Zeitlimit überschritten hat und keine Antwort empfangen wurde. Auch wenn die Aufgabe unmittelbar nach dem Zeitlimit abgeschlossen wird, wird die Antwort von der Clientbibliothek nicht empfangen.