Konfigurering af forsøgslogik i Spring Batch

1. Oversigt

Som standard mislykkes et Spring-batchjob for eventuelle fejl, der er rejst under udførelsen. Men til tider vil vi måske forbedre vores applikations modstandsdygtighed over for intermitterende fejl.

I denne hurtige vejledning vi udforsker, hvordan du konfigurerer forsøgslogik i Spring Batch-rammen.

2. Et eksempel på brugssag

Lad os sige, at vi har et batchjob, der læser en input-CSV-fil:

brugernavn, bruger-id, transaktionsdato, transaktionsbeløb sammy, 1234, 31/10/2015, 10000 john, 9999, 3/12/2015, 12321

Derefter behandler den hver post ved at trykke på et REST-slutpunkt for at hente brugerens alder og postnummer egenskaber:

offentlig klasse RetryItemProcessor implementerer ItemProcessor {@Override offentlig transaktionsproces (Transaktionstransaktion) kaster IOException {log.info ("RetryItemProcessor, forsøger at behandle: {}", transaktion); HttpResponse respons = fetchMoreUserDetails (transaction.getUserId ()); // parse brugerens alder og postkode fra svar og opdater transaktion ... retur transaktion; } ...}

Og endelig genererer det et konsolideret output XML:

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

3. Tilføjelse af forsøg til ItemProcessor

Hvad nu, hvis forbindelsen til REST-slutpunktet afvikles på grund af en langsom netværksnetværk? I så fald mislykkes vores batchjob.

I sådanne tilfælde foretrækker vi, at den mislykkede varebehandling gentages et par gange. Også, lad os konfigurere vores batchjob til at udføre op til tre forsøg i tilfælde af fejl:

@Bean public Step retryStep (ItemProcessor processor, ItemWriter Writer) kaster ParseException {return stepBuilderFactory .get ("retryStep") .chunk (10) .reader (itemReader (inputCsv)) .processor (processor) .writer (writer) .faultTolerant ( ) .retryLimit (3) .retry (ConnectTimeoutException.class) .retry (DeadlockLoserDataAccessException.class) .build (); }

Her har vi et kald til fejl tolerant() til aktivering af forsøgsfunktionalitet. Derudover vi bruger prøve igen og prøv igenLimit for at definere de undtagelser, der er kvalificerede til et nyt forsøg og det maksimale antal igen for henholdsvis en vare.

4. Test af forsøgene

Lad os have et testscenarie, hvor REST-slutpunktet vender tilbage alder og postnummer var nede bare et stykke tid. I dette testscenarie får vi en ConnectTimeoutException kun for de første to API-opkald, og det tredje opkald lykkes:

@Test offentlig ugyldig nårEndpointFailsTwicePasses3rdTime_thenSuccess () kaster undtagelse {FileSystemResource expectResult = ny FileSystemResource (EXPECTED_OUTPUT); FileSystemResource actualResult = ny FileSystemResource (TEST_OUTPUT); når (httpResponse.getEntity ()) .thenReturn (ny StringEntity ("{\" age \ ": 10, \" postCode \ ": \" 430222 \ "}")); // mislykkes ved de første to opkald og videresender tredje gang, når (httpClient.execute (any ())) .thenThrow (new ConnectTimeoutException ("Timeout count 1")) .thenThrow (new ConnectTimeoutException ("Timeout count 2")). thenReturn (httpResponse); JobExecution jobExecution = jobLauncherTestUtils .launchJob (defaultJobParameters ()); JobInstance actualJobInstance = jobExecution.getJobInstance (); ExitStatus actualJobExitStatus = jobExecution.getExitStatus (); assertThat (actualJobInstance.getJobName (), er ("retryBatchJob")); assertThat (actualJobExitStatus.getExitCode (), er ("KOMPLET")); AssertFile.assertFileEquals (expectResult, actualResult); }

Her blev vores job afsluttet med succes. Derudover er det tydeligt fra logfiler, at den første plade med id = 1234 mislykkedes to gange og lykkedes endelig ved tredje forsøg igen:

19: 06: 57.742 [main] INFO osbatch.core.job.SimpleStepHandler - Udførelsestrin: [retryStep] 19: 06: 57.758 [main] INFO obbatch.service.RetryItemProcessor - Forsøg på at behandle bruger med id = 1234 19: 06: 57.758 [main] INFO obbatch.service.RetryItemProcessor - Forsøg på at behandle bruger med id = 1234 19: 06: 57.758 [main] INFO obbatch.service.RetryItemProcessor - Forsøg på at behandle bruger med id = 1234 19:06: 57.758 [main] INFO obbatch.service.RetryItemProcessor - Forsøg på at behandle bruger med id = 9999 19: 06: 57.773 [main] INFO osbatch.core.step.AbstractStep - Trin: [retryStep] udført i 31ms

Lad os ligeledes have en anden testsag for at se, hvad der sker, når alle forsøg er opbrugt:

@Test offentligt ugyldigt nårEndpointAlwaysFail_thenJobFails () kaster undtagelse {når (httpClient.execute (any ())) .thenThrow (ny ConnectTimeoutException ("Endpoint er nede")); JobExecution jobExecution = jobLauncherTestUtils .launchJob (defaultJobParameters ()); JobInstance actualJobInstance = jobExecution.getJobInstance (); ExitStatus actualJobExitStatus = jobExecution.getExitStatus (); assertThat (actualJobInstance.getJobName (), er ("retryBatchJob")); assertThat (actualJobExitStatus.getExitCode (), er ("FAILED")); assertThat (actualJobExitStatus.getExitDescription (), indeholderString ("org.apache.http.conn.ConnectTimeoutException")); }

I dette tilfælde, tre forsøg blev forsøgt for den første post, før jobbet endelig mislykkedes på grund af en ConnectTimeoutException.

5. Konfiguration af forsøg ved hjælp af XML

Lad os endelig se på XML-ækvivalenten for ovenstående konfigurationer:

6. Konklusion

I denne artikel lærte vi, hvordan du konfigurerer forsøgslogik i Spring Batch. Vi så på både Java- og XML-konfigurationer.

Vi brugte også en enhedstest for at se, hvordan forsøgene fungerede i praksis.

Som altid er eksempelkoden til denne vejledning tilgængelig på GitHub.


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