Google Cloud 对于预计需要相当长的时间才能完成的调用(例如,预配 Compute Engine 实例或初始化 Dataflow 流水线),API 会使用长时间运行的操作 (LRO)。这些 API 在任务运行时不会保持活跃的长期有效连接或阻塞。对于 LRO API,Java 版 Cloud 客户端库会返回一个 future,供您稍后检查。
确定 API 是否为 LRO
您可以通过以下两种主要方式来确定 API 是否为 LRO:
- LRO API 的后缀为
Async(例如createClusterAsync)或OperationCallable(例如createClusterOperationCallable)。 - LRO API 会返回
OperationFuture或OperationCallable。
以下代码段展示了这两种变体,并以 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()
这两种变体针对的是同一 API,而不是两个不同的 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任务已被取消。当调用超出总超时时间且未收到响应时,客户端库会抛出此异常。即使任务在超时后立即完成,客户端库也不会看到响应。