Google Cloud API は、完了に時間がかかることが予想される呼び出し(Compute Engine インスタンスのプロビジョニングや Dataflow パイプラインの初期化など)に長時間実行オペレーション(LRO)を使用します。これらの API は、タスクの実行中にアクティブな長時間接続を維持したり、ブロックしたりしません。LRO API の場合、Java 用 Cloud クライアント ライブラリは、後で確認できるように future を返します。
API が LRO かどうかを判断する
API が LRO かどうかを判断する主な方法は 2 つあります。
- LRO API には、接尾辞
Async(createClusterAsyncなど)またはOperationCallable(createClusterOperationCallableなど)があります。 - LRO API は
OperationFutureまたはOperationCallableを返します。
次のスニペットは、Java-Dataproc を例として、2 つのバリエーションを示しています。
// 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()
これらは同じ API の 2 つのバリエーションであり、2 つの異なる API ではありません(どちらの呼び出しも Dataproc クラスタを作成します)。Async バリアントをおすすめします。
LRO の大まかなフロー
LRO API は、基本的に、最初のリクエスト呼び出しの後に一連の小さなポーリング呼び出しが続きます。最初の呼び出しでリクエストが送信され、サーバーに「オペレーション」が作成されます。サーバーに対する後続のポーリング呼び出しはすべて、オペレーションのステータスを追跡します。オペレーションが終了すると、レスポンスが返されます。それ以外の場合は、不完全なステータスが返され、クライアント ライブラリが再度ポーリングするかどうかを決定します。
デフォルトでは、クライアントがポーリング ロジックを処理するため、特定の要件がない限り、ポーリング メカニズムを構成する必要はありません。
ユーザーの視点から見ると、レスポンスが受信されるまで呼び出しはバックグラウンドで実行されます。ポーリング呼び出しとタイムアウト構成には、サービスチームが API の想定時間に基づいて事前構成したデフォルト値があります。これらの構成は、ポーリングの頻度や、あきらめるまでの待機時間など、多くの要因を制御します。
Java 用 Cloud クライアント ライブラリは、OperationFuture を使用して LRO を操作するためのインターフェースを提供します。
次のスニペットは、Java-Dataproc を例として、オペレーションを呼び出してレスポンスを待つ方法を示しています。
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.
}
デフォルトの LRO 値
デフォルト値は、各クライアントの StubSettings クラスにあります。initDefaults() メソッドは、ネストされた Builder クラス内の LRO 設定を初期化します。
たとえば、Java-Aiplatform v3.24.0 では、deployModel LRO 呼び出しに次のデフォルト パラメータがあります。
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()));
再試行と LRO はどちらも同じ RetrySettings クラスを共有します。次の表に、RetrySettings 内のフィールドと LRO 機能のマッピングを示します。
| RetrySettings | 説明 |
|---|---|
| InitialRetryDelay | 最初のポーリングまでの初期遅延。 |
| MaxRetryDelay | 各ポーリング間の最大遅延。 |
| RetryDelayMultiplier | ポーリング間のポーリング再試行遅延の乗数。 |
| TotalTimeoutDuration | 長時間実行オペレーションに許容される最長時間。 |
LRO 値を構成するタイミング
LRO 値を手動で構成する主なユースケースは、LRO タイムアウトのためにポーリング頻度を変更することです。デフォルト値はサービスチームによって推定値として構成されていますが、特定の要因により、タイムアウトが発生することがあります。
タイムアウトの数を減らすには、合計タイムアウト値を増やします。他の値を増やすことも有効です。期待どおりの動作になるようにテストする必要があります。
LRO 値の構成方法
LRO 値を構成するには、OperationTimedPollAlgorithm オブジェクトを作成し、特定の LRO のポーリング アルゴリズムを更新します。次のスニペットでは、例として Java-Dataproc を使用しています。
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());
この構成では、createClusterOperation RPC の LRO 値のみが変更されます。クライアントの他の RPC は、変更されない限り、各 RPC に事前構成された LRO 値を引き続き使用します。
LRO タイムアウト
合計タイムアウトを超えない限り、ライブラリはポーリングを続行します。合計タイムアウトを超えると、ライブラリは「タスクがキャンセルされました」というメッセージとともに java.util.concurrent.CancellationException をスローします。
CancellationException は、バックエンド Google Cloudタスクがキャンセルされたことを意味しません。この例外は、呼び出しが合計タイムアウトを超過し、レスポンスを受信しなかった場合にクライアント ライブラリからスローされます。タイムアウトの直後にタスクが完了した場合でも、レスポンスはクライアント ライブラリに表示されません。