Hosszú ideig futó műveletek a Javához készült Azure SDK-ban

Ez a cikk a Java Azure SDK hosszú ideig futó műveleteit ismerteti, és bemutatja, hogyan követheti nyomon az előrehaladást, és hogyan kérdezheti le a végső eredményeket kevésbé manuális lekérdezési logikával.

Bizonyos műveletek Azure hosszabb időt vesznek igénybe. Ezek a műveletek nem követik a gyors kérések és válaszok szokásos HTTP-stílusát. A forrás URL-címéről például egy Storage-blobba másolt adatok, vagy az űrlapok felismerésére szolgáló modell betanítása olyan műveletek, amelyek néhány másodperctől több percig is eltarthatnak. Ezek a műveletek hosszú ideig futó műveletek, amelyeket gyakran LRO-ként rövidítünk. Az LRO a kért művelettől és a kiszolgáló által végrehajtandó folyamattól függően másodperceket, perceket, órákat, napokat vagy hosszabb időt is igénybe vehet.

A Azure Java ügyfélkódtáraiban minden hosszú ideig futó művelet az begin előtaggal kezdődik. Ez az előtag azt jelzi, hogy a művelet hosszú ideig fut, és hogy a művelettel való interakció módja kissé eltér a szokásos kérés- és válaszfolyamattól. Az előtag mellett begin a művelet visszatérési típusa is eltér a szokásostól, így lehetővé teszi a hosszú ideig futó műveletek teljes körét. A Java Azure SDK legtöbb dologához hasonlóan a hosszú ideig futó műveletek szinkron és aszinkron API-kkal is rendelkeznek:

  • A szinkron kliensek esetén a hosszan futó műveletek a SyncPoller egy példányát adják vissza.
  • Az aszinkron kliensekben a hosszan futó műveletek a PollerFlux egy példányát adják vissza.

Mind a SyncPoller, mind a PollerFlux ügyféloldali absztrakciók, amelyek leegyszerűsítik a hosszú ideig futó kiszolgálóoldali műveletekkel való kapcsolattartást. A cikk további része az ilyen típusok használatakor ajánlott eljárásokat ismerteti.

Szinkron, hosszú ideig futó műveletek

Amikor egy olyan API-t hív meg, amely visszaad egy SyncPollerértéket, a hosszú ideig futó művelet azonnal elindul. Az API azonnal visszaadja az SyncPoller eredményt, így nyomon követheti a hosszú ideig futó művelet előrehaladását, és lekérheti a végeredményt. Az alábbi példa bemutatja, hogyan figyelheti meg egy hosszú ideig futó művelet előrehaladását a 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());

Ez a példa a poll() metódust használja a SyncPoller hosszú ideig futó művelet előrehaladásával kapcsolatos információk lekéréséhez. Ez a kód kinyomtatja az állapotot a konzolon, de egy jobb implementáció ennek az állapotnak a alapján hoz releváns döntéseket.

A getRetryAfter() metódus információt ad vissza arról, hogy mennyi ideig kell várni a következő szavazás előtt. A legtöbb Azure hosszú ideig futó művelet a HTTP-válasz részeként adja vissza a poll késleltetését (azaz a gyakran használt retry-after fejlécet). Ha a válasz nem tartalmazza a lekérdezés késleltetését, a getRetryAfter() metódus a hosszú ideig futó művelet meghívásakor megadott időtartamot adja vissza.

Az előző példa egy hurkot do..while használ a hosszú ideig futó művelet befejezéséig történő ismételt lekérdezéshez. Ha nem érdeklik ezek a köztes eredmények, akkor ehelyett meghívhatja a waitForCompletion() függvényt. Ez a hívás blokkolja az aktuális szálat, amíg a hosszú ideig futó művelet befejeződik, és visszaadja az utolsó szavazási választ:

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

Ha az utolsó szavazási válasz azt jelzi, hogy a hosszú ideig futó művelet sikeresen befejeződött, a végeredményt a következővel getFinalResult()érheti el:

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

További hasznos API-k a SyncPoller következők:

  • waitForCompletion(Duration): várja meg, amíg a hosszú ideig futó művelet befejeződik, a megadott időtúllépési időtartamig.
  • waitUntil(LongRunningOperationStatus): várjon, amíg a megadott hosszú ideig futó művelet állapota megérkezik.
  • waitUntil(LongRunningOperationStatus, Duration): várjon, amíg a megadott hosszú ideig futó művelet állapota meg nem érkezik, vagy amíg a megadott időtúllépési időtartam lejár.

Aszinkron, hosszú ideig futó műveletek

Az alábbi példa bemutatja, hogyan követhet nyomon egy hosszú ideig futó műveletet a(z) PollerFlux segítségével. Az aszinkron API-kban a hálózati hívások más szálon történnek, mint a fő szál, amely meghívja subscribe(). Ez az architektúra azt jelenti, hogy a fő szál az eredmény rendelkezésre állása előtt leállhat. Győződjön meg arról, hogy az alkalmazás nem lép ki az aszinkron művelet befejeződése előtt.

Az async API azonnal visszaad egy PollerFlux elemet, de maga a hosszú ideig futó művelet nem indul el, amíg nem iratkozik fel a PollerFlux elemre. Ez a folyamat az összes Flux-alapú API működésének módja. Az alábbi példa egy hosszú ideig futó aszinkron műveletet mutat be:

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

Az alábbi példában időszakos állapotfrissítéseket kap a hosszan futó műveletről. Ezekkel a frissítésekkel megállapíthatja, hogy a hosszú ideig futó művelet továbbra is a várt módon működik-e. Ez a példa kinyomtatja az állapotot a konzolon, de egy jobb implementáció az állapot alapján releváns hibakezelési döntéseket hozna.

Ha nem érdeklik a köztes állapotfrissítések, és csak értesítést szeretne kapni a végleges eredményről, használja az alábbi példához hasonló kódot:

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

Ebben a kódban a hosszú ideig futó művelet végeredményét kéri le a last() hívásával. Ez a hívás jelzi a PollerFlux számára, hogy meg szeretné várni az összes lekérdezési ciklus befejezését. Ezen a ponton a hosszú ideig futó művelet eléri a terminálállapotot, és megvizsgálhatja annak állapotát az eredmény meghatározásához. Ha a lekérdezés azt jelzi, hogy a hosszú ideig futó művelet sikeresen befejeződött, lekérheti a végeredményt, és továbbíthatja a fogyasztónak az előfizetési hívásban.

Következő lépések

Most, hogy már ismeri az Azure SDK for Java régóta futó API-jait, tekintse meg a Proxyk konfigurálása az Azure SDK for Java-ban című témakört, amelyből megtudhatja, hogyan szabhatja testre a HTTP-ügyfelet.