この記事では、Azure SDK for Java で実行時間の長い操作を使用する方法の概要について説明します。
Azure での特定の操作の完了には、長時間かかる場合があります。 これらの操作は、標準の HTTP スタイルのクイック要求/応答フローの範囲外です。 たとえば、ソース URL からストレージ BLOB にデータをコピーしたり、モデルをトレーニングしてフォームを認識したりする操作は、数秒から数分かかる場合があります。 このような操作は Long-Running Operations と呼ばれ、多くの場合、"LRO" と省略されます。 LRO は、要求された操作とサーバー側で実行する必要があるプロセスに応じて、秒、分、時間、日、または長い時間がかかる場合があります。
Azure 用 Java クライアント ライブラリには、実行時間の長い操作はすべて begin
プレフィックスで始まるという規則が存在します。 このプレフィックスは、この操作の実行時間が長く、この操作との対話手段が通常の要求/応答フローとは若干異なっていることを示します。
begin
プレフィックスと共に、操作からの戻り値の型も通常とは異なり、実行時間の長い操作機能の全範囲を有効にします。 Azure SDK for Java のほとんどの場合と同様に、実行時間の長い操作には同期 API と非同期 API の両方があります。
- 同期クライアントでは、実行時間の長い操作は
SyncPoller
インスタンスを返します。 - 非同期クライアントでは、実行時間の長い操作は
PollerFlux
インスタンスを返します。
SyncPoller
とPollerFlux
はどちらも、実行時間の長いサーバー側操作との対話を簡略化することを目的としたクライアント側の抽象化です。 この記事の残りの部分では、これらの型を使用する場合のベスト プラクティスについて説明します。
実行時間の長い同期操作
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 は次のとおりです。
-
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
に通知します。この時点で、実行時間の長い操作が終了状態に達し、その状態を調べて結果を確認できます。 長時間実行される操作が正常に完了したことをポーラーが示した場合は、最終結果を取得し、それをサブスクライブ呼び出しで消費者に渡すことができます。
次のステップ
Azure SDK for Java で実行時間の長い API について理解したら、HTTP クライアントをさらにカスタマイズする方法については、 Azure SDK for Java でのプロキシの構成 に関するページを参照してください。