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

本文概述了如何使用 Azure SDK for Java 的长时间运行操作。

Azure 上的某些作可能需要较长的时间才能完成。 这些操作超出了标准 HTTP 快速请求/响应流程。 例如,将数据从源 URL 复制到存储 Blob,或训练模型来识别表单,这些作可能需要几秒钟到几分钟的时间。 此类操作称为 Long-Running 操作,通常缩写为“LRO”。 LRO 可能需要几秒钟、分钟、小时、天或更长时间才能完成,具体取决于请求的作以及必须在服务器端执行的过程。

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

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

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

同步长时间运行的操作

调用任何返回 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());

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

该方法 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 包括:

  1. waitForCompletion(Duration):等待长时间运行的操作完成,等待给定的超时时间。
  2. waitUntil(LongRunningOperationStatus):等待直到收到给定的长时间运行操作状态。
  3. 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 你希望等待所有轮询完成,此时长时间运行的操作已达到最终状态,你可以检查其状态以确定结果。 如果轮询器指示长时间运行的操作已成功完成,则可以检索最终结果并将其传递给订阅调用中的使用者。

后续步骤

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