適用於 Java 的 Azure SDK 中長時間執行的作業

本文說明 Azure SDK for Java 中長期執行的操作,並展示如何以較少手動輪詢邏輯追蹤進度與取得最終結果。

Azure 上的某些操作需要較長時間才能完成。 這些操作不遵循標準 HTTP 格式的快速請求與回應流程。 例如,將資料從來源網址複製到 Storage blob,或訓練模型辨識表單,這些操作可能需要幾秒鐘到幾分鐘。 這些行動是長期進行的,通常簡稱為LRO。 LRO 可能花費數秒、分鐘、數小時、數天甚至更長時間完成,視所請求的操作及伺服器必須執行的程序而定。

在 Azure 的 Java 用戶端程式庫中,所有長時間執行的作業都以 begin 前綴開頭。 此前綴表示該操作是長期執行的,且與此操作的互動方式與一般請求與回應流程略有不同。 除了 begin 前綴之外,作業的傳回類型也不同於一般情況,以啟用長時間運行作業功能的完整範圍。 與 Azure SDK for Java 中的大多數功能一樣,長期執行的操作同時包含同步與非同步 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());

此範例會使用 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,請參閱在 適用於 Java 的 Azure SDK 中設定 Proxy ,以瞭解如何進一步自定義 HTTP 用戶端。