适用于 Java 的 Azure SDK 中的长时间运行操作

本文介绍Java Azure SDK中长时间运行的操作,并演示如何使用更少的手动轮询逻辑跟踪进度和检索最终结果。

对Azure的某些操作需要较长的时间才能完成。 这些操作不遵循快速请求和响应流的标准 HTTP 样式。 例如,将数据从源 URL 复制到存储 Blob,或训练模型来识别表单,这些操作可能需要几秒钟到几分钟的时间。 这些操作是长时间运行的操作,通常缩写为 LRO。 LRO 可能需要几秒钟、分钟、小时、天或更长时间才能完成,具体取决于请求的操作以及服务器必须执行的进程。

在用于Azure的Java客户端库中,所有长时间运行的操作都以begin前缀开头。 此前缀表示操作长时间运行,并且与此操作的交互方式与通常的请求和响应流略有不同。 除了 begin 前缀之外,操作的返回类型也与平常不同,以启用全部的长时间运行操作功能。 与Java Azure SDK中的大多数操作一样,长时间运行的操作同时具有同步和异步 API:

  • 在同步客户端中,长时间运行的操作返回实例 SyncPoller
  • 在异步客户端中,长时间运行的操作返回一个 PollerFlux 实例。

SyncPollerPollerFlux 都是客户端抽象,可简化与服务器端长时间运行的操作的交互。 本文的其余部分概述了使用这些类型的最佳做法。

同步长时间运行的操作

调用返回 a SyncPoller的 API 时,长时间运行的操作会立即启动。 API 会立即返回 SyncPoller ,因此可以监视长时间运行的操作的进度并获取最终结果。 以下示例演示如何使用 SyncPoller 监控长时间运行操作的进度。

SyncPoller<UploadBlobProgress, UploadedBlobProperties> poller = syncClient.beginUploadFromUri(<URI to upload from>);
PollResponse<UploadBlobProgress> response;

do {
    response = poller.poll();
    System.out.println("Status of long running upload operation: " + response.getStatus());
    Duration pollInterval = response.getRetryAfter();
    TimeUnit.MILLISECONDS.sleep(pollInterval.toMillis());
} while (!response.getStatus().isComplete());

此示例使用 SyncPoller 上的 poll() 方法来获取有关长时间运行操作进度的信息。 此代码将状态打印到控制台,但更好的实现会根据此状态做出相关决策。

该方法 getRetryAfter() 返回有关下一轮投票之前等待多长时间的信息。 大多数 Azure 长时间运行的操作将轮询延迟作为其 HTTP 响应的一部分返回(即常用的 retry-after 标头)。 如果响应不包含轮询延迟,该方法 getRetryAfter() 将返回调用长时间运行的操作时给定的持续时间。

前面的示例使用循环 do..while 重复轮询,直到长时间运行的操作完成。 如果对这些中间结果不感兴趣,可以改为调用 waitForCompletion()。 此调用会阻止当前线程,直到长时间运行的操作完成并返回最后一个轮询响应:

PollResponse<UploadBlobProgress> response = poller.waitForCompletion();

如果最后一次轮询响应表明该长时间运行的操作已成功完成,则可以使用 getFinalResult() 获取最终结果:

if (LongRunningOperationStatus.SUCCESSFULLY_COMPLETED == response.getStatus()) {
    UploadedBlobProperties result = poller.getFinalResult();
}

SyncPoller 中,其他有用的 API 包括:

  • waitForCompletion(Duration):在给定的超时时间内等待长时间运行操作完成。
  • waitUntil(LongRunningOperationStatus):等待直到收到给定的长时间运行操作状态。
  • waitUntil(LongRunningOperationStatus, Duration):等待直到收到给定的长时间运行操作状态,或者直到给定的超时时间到期。

异步长时间运行的操作

以下示例说明了 PollerFlux 如何让您观察长时间运行的操作。 在异步 API 中,网络调用发生在与调用 subscribe()的主线程不同的线程中。 此体系结构意味着主线程可能会在结果可用之前终止。 需要在异步操作完成之前确保应用程序不会退出。

异步 API 会立即返回一个 PollerFlux,但长时间运行操作本身要等到你订阅 PollerFlux 之后才会启动。 此过程是所有基于Flux的 API 运作的方式。 以下示例演示异步长时间运行的操作。

asyncClient.beginUploadFromUri(...)
    .subscribe(response -> System.out.println("Status of long running upload operation: " + response.getStatus()));

在以下示例中,你会收到有关长时间运行的操作的间歇性状态更新。 可以利用这些更新来确定长时间运行的操作是否仍以预期的方式运行。 此示例将状态打印到控制台,但更好的实现将基于此状态做出相关的错误处理决策。

如果你对中间状态更新不感兴趣,并且只想在到达最终结果时收到通知,请使用类似于以下示例的代码:

asyncClient.beginUploadFromUri(...)
    .last()
    .flatMap(response -> {
        if (LongRunningOperationStatus.SUCCESSFULLY_COMPLETED == response.getStatus()) {
            return response.getFinalResult();
        }
        return Mono.error(new IllegalStateException("Polling completed unsuccessfully with status: "+ response.getStatus()));
    })
    .subscribe(
        finalResult -> processFormPages(finalResult),
        ex -> countDownLatch.countDown(),
        () -> countDownLatch.countDown());

在此代码中,通过调用 last() 检索长时间运行操作的最终结果。 此调用告知 PollerFlux 你希望等待所有轮询完成。 此时,长时间运行的操作达到终端状态,可以检查其状态以确定结果。 如果轮询器显示长时间运行的操作已成功完成,则可以检索最终结果,并在 subscribe 调用中将其传递给使用方。

后续步骤

熟悉用于 Java 的 Azure SDK 中长时间运行的 API 后,请参阅 Azure SDK for Java 中的“配置代理 ”,了解如何进一步自定义 HTTP 客户端。