Konfigurácia logiky opakovania v Spring Batch

1. Prehľad

V predvolenom nastavení jarná dávková úloha zlyhá pre všetky chyby vzniknuté počas jej vykonávania. Niekedy však možno budeme chcieť vylepšiť odolnosť našej aplikácie, aby sme sa vyrovnali s občasnými zlyhaniami.

V tomto rýchlom návode preskúmame, ako nakonfigurovať logiku opakovania v rámci Spring Batch.

2. Príklad použitia

Povedzme, že máme dávkovú úlohu, ktorá číta vstupný súbor CSV:

používateľské meno, identifikátor používateľa, dátum transakcie, suma transakcie sammy, 1234, 31/10/2015, 10 000 john, 9999, 3. 12. 2015, 12321

Potom spracuje každý záznam klepnutím na koncový bod REST, aby sa načítal údaj používateľa Vek a postCode atribúty:

verejná trieda RetryItemProcessor implementuje ItemProcessor {@Override verejný transakčný proces (transakčná transakcia) vyvolá IOException {log.info ("RetryItemProcessor, pokus o spracovanie: {}", transakcia); HttpResponse response = fetchMoreUserDetails (transaction.getUserId ()); // analyzovať vek používateľa a postCode z reakcie a aktualizovať transakciu ... návratová transakcia; } ...}

A nakoniec generuje konsolidovaný výstup XML:

  10000.0 2015-10-31 00:00:00 1234 sammy 10 430222 ... 

3. Pridanie pokusov do ItemProcessor

Čo teraz, ak pripojenie k koncovému bodu REST vyprší z dôvodu nejakej pomalosti siete? Ak je to tak, naša dávková práca zlyhá.

V takýchto prípadoch by sme uprednostnili opakované pokusy o zlyhanie spracovania položky. A tak, nakonfigurujme našu dávkovú úlohu tak, aby v prípade zlyhania vykonala až tri pokusy:

@Bean public Step retryStep (procesor ItemProcessor, zapisovač ItemWriter) hodí ParseException {return stepBuilderFactory .get ("retryStep") .chunk (10) .reader (itemReader (inputCsv)) .processor (procesor) .writer (spisovateľ). DefaultTolerant ( ) .retryLimit (3) .retry (ConnectTimeoutException.class) .retry (DeadlockLoserDataAccessException.class) .build (); }

Máme tu hovor odolné proti chybám() na povolenie funkcie opakovania. Navyše, používame skúsiť znova a retryLimit definovať výnimky, ktoré sa kvalifikujú na opakovanie, a maximálny počet opakovaní za položku, resp.

4. Testovanie pokusov

Poďme mať testovací scenár, kde sa vráti koncový bod REST Vek a postCode bol dole len na chvíľu. V tomto testovacom scenári dostaneme a ConnectTimeoutException iba pre prvé dve volania API a tretie volanie bude úspešné:

@Test public void whenEndpointFailsTwicePasses3rdTime_thenSuccess () vyvolá výnimku {FileSystemResource expectResult = nový FileSystemResource (EXPECTED_OUTPUT); FileSystemResource actualResult = nový FileSystemResource (TEST_OUTPUT); when (httpResponse.getEntity ()) .thenReturn (new StringEntity ("{\" age \ ": 10, \" postCode \ ": \" 430222 \ "}")); // zlyhá pri prvých dvoch hovoroch a prejde tretíkrát ďalej, keď (httpClient.execute (any ())) .thenThrow (nový ConnectTimeoutException ("časový limit počet 1")) .thThThrow (nový ConnectTimeoutException ("časový limit počet 2")). thenReturn (httpResponse); JobExecution jobExecution = jobLauncherTestUtils .launchJob (defaultJobParameters ()); JobInstance actualJobInstance = jobExecution.getJobInstance (); ExitStatus actualJobExitStatus = jobExecution.getExitStatus (); assertThat (actualJobInstance.getJobName (), je ("retryBatchJob")); assertThat (actualJobExitStatus.getExitCode (), je ("DOKONČENÉ")); AssertFile.assertFileEquals (expectResult, actualResult); }

Tu sa naša práca úspešne dokončila. Z protokolov je navyše zrejmé, že prvý záznam s id = 1234 dvakrát neuspel a nakoniec uspel pri treťom pokuse:

19: 06: 57,742 [main] INFO osbatch.core.job.SimpleStepHandler - krok vykonania: [retryStep] 19: 06: 57.758 [main] INFO obbatch.service.RetryItemProcessor - pokus o spracovanie používateľa s id = 1234 19: 06: 57.758 [main] INFO obbatch.service.RetryItemProcessor - Pokus o spracovanie používateľa s id = 1234 19: 06: 57.758 [main] INFO obbatch.service.RetryItemProcessor - Pokus o spracovanie používateľa s id = 1234 19:06: 57.758 [main] INFO obbatch.service.RetryItemProcessor - Pokus o spracovanie používateľa s id = 9999 19: 06: 57.773 [main] INFO osbatch.core.step.AbstractStep - Krok: [retryStep] vykonaný za 31 ms

Podobne si dajme ďalší testovací prípad, ktorý sleduje, čo sa stane, keď sa vyčerpajú všetky pokusy:

@Test public void whenEndpointAlwaysFail_thenJobFails () vyvolá výnimku {when (httpClient.execute (any ())) .thThTh (new ConnectTimeoutException ("Endpoint is down")); JobExecution jobExecution = jobLauncherTestUtils .launchJob (defaultJobParameters ()); JobInstance actualJobInstance = jobExecution.getJobInstance (); ExitStatus actualJobExitStatus = jobExecution.getExitStatus (); assertThat (actualJobInstance.getJobName (), je ("retryBatchJob")); assertThat (actualJobExitStatus.getExitCode (), je ("FAILED")); assertThat (actualJobExitStatus.getExitDescription (), containsString ("org.apache.http.conn.ConnectTimeoutException")); }

V tomto prípade, o prvý záznam sa pokúsili tri pokusy predtým, ako úloha nakoniec zlyhala kvôli a ConnectTimeoutException.

5. Konfigurácia pokusov pomocou XML

Na záver sa pozrime na ekvivalent XML vyššie uvedených konfigurácií:

6. Záver

V tomto článku sme sa naučili, ako nakonfigurovať logiku opakovania v Spring Batch. Pozreli sme sa na konfiguráciu Java aj XML.

Použili sme tiež test jednotky, aby sme zistili, ako pokusy fungovali v praxi.

Vzorový kód tohto tutoriálu je ako vždy k dispozícii na GitHub.


$config[zx-auto] not found$config[zx-overlay] not found