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

Ez a cikk áttekintést nyújt a javai Azure SDK-val végzett hosszú ideig futó műveletek használatáról.

Bizonyos azure-beli műveletek végrehajtása hosszabb időt vehet igénybe. Ezek a műveletek nem tartoznak a gyors kérések/ válaszfolyamatok szabványos HTTP-stílusához. A forrás URL-címéről például egy Storage-blobba másolhat adatokat, vagy betanítást végezhet egy modellben az űrlapok felismerésére, ez néhány másodperctől néhány percig is eltarthat. Ezeket a műveleteket hosszú ideig futó műveleteknek nevezzük, és gyakran rövidítve "LRO"-ként. Az LRO végrehajtása a kért művelettől és a kiszolgálóoldalon végrehajtandó folyamattól függően másodperceket, perceket, órákat, napokat vagy hosszabb időt is igénybe vehet.

Az Azure Java-ügyfélkódtáraiban létezik egy konvenció, amely szerint minden hosszú ideig futó művelet az begin előtaggal kezdődik. Ez az előtag azt jelzi, hogy ez 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-hoz készült Azure SDK-ban a legtöbb dologhoz hasonlóan szinkron és aszinkron API-k is léteznek a hosszú ideig futó műveletekhez:

  • Szinkron ügyfelek esetén a hosszan futó műveletek egy példányt SyncPoller adnak vissza.
  • Az aszinkron ügyfelekben a hosszan futó műveletek egy példányt PollerFlux adnak vissza.

Mindkettő SyncPoller , és PollerFlux az ügyféloldali absztrakciók célja a hosszú ideig futó kiszolgálóoldali műveletek közötti interakció egyszerűsítése. A cikk további része az ilyen típusok használatakor ajánlott eljárásokat ismerteti.

Szinkron, hosszú ideig futó műveletek

A visszaküldött API-k SyncPoller meghívása azonnal elindítja a hosszú ideig futó műveletet. 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() módszer SyncPoller használatával kéri le a hosszú ideig futó művelet előrehaladásával kapcsolatos információkat. Ez a kód kinyomtatja az állapotot a konzolon, de egy jobb implementáció az állapot alapján releváns döntéseket hozna.

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-beli hosszú ideig futó művelet a HTTP-válasz részeként adja vissza a lekérdezés 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, akkor a getRetryAfter() metódus a hosszú ideig futó művelet meghívásakor megadott időtartamot adja vissza.

A fenti példa 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 hívhatja.waitForCompletion() Ez a hívás addig blokkolja az aktuális szálat, amíg a hosszan futó művelet be nem fejező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ény a következővel getFinalResult()kérhető le:

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

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

  1. waitForCompletion(Duration): várja meg, amíg a hosszú ideig futó művelet befejeződik, a megadott időtúllépési időtartamig.
  2. waitUntil(LongRunningOperationStatus): várjon, amíg a megadott hosszú ideig futó művelet állapota megérkezik.
  3. 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 lehet megfigyelni egy PollerFlux hosszú ideig futó műveletet. Az aszinkron API-kban a hálózati hívások egy másik szálon zajlnak, mint a hívást kezdeményező subscribe()fő szál. Ez azt jelenti, hogy a fő szál az eredmény rendelkezésre állása előtt leállhat. Önnek kell gondoskodnia arról, hogy az alkalmazás ne lépjen ki, mielőtt az aszinkron művelet befejeződik.

Az aszinkron API azonnal visszaadja PollerFlux a műveletet, de maga a hosszú ideig futó művelet nem indul el, amíg elő nem iratkozik a PollerFlux. Ez a folyamat az összes Flux-based API működése. 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 fog kapni a hosszú ideig 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, az alábbi példához hasonló kódot használhat:

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 hívja meg last(). Ez a PollerFlux hívás azt jelzi, hogy várnia kell az összes lekérdezés befejezésére, ekkor a hosszú ideig futó művelet elérte a terminálállapotot, és az eredmény meghatározásához megvizsgálhatja annak állapotát. 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 azt a fogyasztónak az előfizetési hívásban.

További 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.