Długotrwałe operacje w pakiecie SDK Azure dla języka Java

W tym artykule opisano długotrwałe operacje w Azure SDK dla Java i pokazano, jak śledzić postęp i pobierać wyniki końcowe przy użyciu mniej ręcznej logiki sondowania.

Niektóre operacje na Azure potrwają dłuższy czas. Te operacje nie są zgodne ze standardowym stylem HTTP szybkiego żądania i przepływu odpowiedzi. Na przykład kopiowanie danych ze źródłowego adresu URL do obiektu blob usługi Storage lub trenowanie modelu do rozpoznawania formularzy to operacje, które mogą potrwać od kilku sekund do kilku minut. Są to operacje długotrwałe, często określane skrótem LRO. Ukończenie operacji LRO może potrwać kilka sekund, minut, godzin, dni lub dłużej, w zależności od żądanej operacji i procesu, który musi wykonać serwer.

W bibliotekach klienta Java dla Azure wszystkie długotrwałe operacje rozpoczynają się od prefiksubegin. Ten prefiks wskazuje, że operacja jest długotrwała i że sposób interakcji z tą operacją różni się nieco od zwykłego przepływu żądań i odpowiedzi. Wraz z prefiksem begin typ zwracany z operacji jest również inny niż zwykle, aby umożliwić pełne funkcjonowanie długotrwałych operacji. Podobnie jak w przypadku większości elementów w Azure SDK dla Java długotrwałe operacje mają zarówno synchroniczne, jak i asynchroniczne interfejsy API:

  • W klientach synchronicznych długotrwałe operacje zwracają instancję SyncPoller.
  • W przypadku klientów asynchronicznych operacje długotrwałe zwracają instancję PollerFlux.

Zarówno SyncPoller, jak i PollerFlux, są abstrakcjami po stronie klienta, które upraszczają interakcję z długotrwałymi operacjami po stronie serwera. W pozostałej części tego artykułu opisano najlepsze rozwiązania dotyczące pracy z tymi typami.

Synchroniczne długotrwałe operacje

Gdy wywołasz interfejs API, który zwraca SyncPoller, operacja długotrwała rozpoczyna się natychmiast. Interfejs API zwraca SyncPoller natychmiast, dzięki czemu można monitorować postęp długotrwałej operacji i uzyskać wynik końcowy. W poniższym przykładzie pokazano, jak monitorować postęp długotrwałej operacji przy użyciu elementu 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());

W tym przykładzie użyto metody poll() obiektu SyncPoller, aby uzyskać informacje o postępie długotrwałej operacji. Ten kod wyświetla stan konsoli, ale lepsza implementacja podejmuje odpowiednie decyzje na podstawie tego stanu.

Metoda getRetryAfter() zwraca informacje o tym, jak długo czekać przed następnym sondą. Większość długotrwałych operacji platformy Azure zwraca opóźnienie sondowania w ramach odpowiedzi HTTP (to jest w często używanym nagłówku retry-after). Jeśli odpowiedź nie zawiera opóźnienia odpytywania, metoda getRetryAfter() zwraca okres podany podczas wywoływania operacji długotrwałej.

W poprzednim przykładzie użyto do..while pętli do wielokrotnego sondowania do momentu zakończenia długotrwałej operacji. Jeśli nie interesuje Cię te wyniki pośrednie, możesz wywołać metodę waitForCompletion(). To wywołanie blokuje bieżący wątek do momentu zakończenia długotrwałej operacji i zwraca ostatnią odpowiedź odpytywania:

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

Jeśli ostatnia odpowiedź sondy wskazuje, że długotrwała operacja zakończy się pomyślnie, możesz uzyskać wynik końcowy przy użyciu polecenia getFinalResult():

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

Inne przydatne interfejsy API w systemie SyncPoller to:

  • waitForCompletion(Duration): poczekaj na zakończenie operacji długotrwałej przez określony limit czasu.
  • waitUntil(LongRunningOperationStatus): poczekaj na odebranie danego długotrwałego stanu operacji.
  • waitUntil(LongRunningOperationStatus, Duration): poczekaj na odebranie statusu długotrwałej operacji lub upłynięcia danego limitu czasu.

Operacje asynchroniczne długotrwałe

Poniższy przykład pokazuje, jak PollerFlux umożliwia obserwowanie długotrwałej operacji. W asynchronicznych interfejsach API wywołania sieciowe odbywają się w innym wątku niż główny wątek, który wywołuje subscribe(). Ta architektura oznacza, że główny wątek może zakończyć się przed udostępnieniem wyniku. Należy upewnić się, że aplikacja nie kończy działania przed zakończeniem operacji asynchronicznych.

Asynchroniczny interfejs API zwraca PollerFlux natychmiast, ale długotrwała operacja nie rozpoczyna się, dopóki nie zasubskrybujesz elementu PollerFlux. Ten proces polega na tym, jak działają wszystkie interfejsy API oparte na Flux. W poniższym przykładzie przedstawiono operację asynchroniową długotrwałą:

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

W poniższym przykładzie otrzymasz okresowe aktualizacje stanu długotrwałej operacji. Za pomocą tych aktualizacji można określić, czy długotrwała operacja nadal działa zgodnie z oczekiwaniami. W tym przykładzie stan jest wyświetlany w konsoli programu , ale lepsza implementacja pozwoliłaby podejmować odpowiednie decyzje dotyczące obsługi błędów w oparciu o ten stan.

Jeśli nie interesuje Cię aktualizacja stanu pośredniego i po prostu chcesz otrzymywać powiadomienia o końcowym wyniku po nadejściu, użyj kodu podobnego do następującego przykładu:

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());

W tym kodzie pobierasz końcowy wynik długotrwałej operacji, wywołując metodę last(). To wywołanie informuje PollerFlux, że chcesz poczekać na zakończenie całego odpytywania. W tym momencie operacja długotrwała osiąga stan końcowy i można sprawdzić jej stan, aby określić wynik. Jeśli mechanizm odpytywania wskazuje, że operacja długotrwała zakończyła się pomyślnie, możesz pobrać wynik końcowy i przekazać go odbiorcy w wywołaniu funkcji subscribe.

Dalsze kroki

Teraz, gdy znasz długo istniejące interfejsy API w zestawie Azure SDK dla języka Java, zobacz Konfigurowanie serwerów proxy w zestawie Azure SDK dla języka Java, aby dowiedzieć się, jak dalej dostosować klienta HTTP.