Een beknopte handleiding voor time-outs in OkHttp

1. Overzicht

In deze korte tutorial zullen we ons concentreren op verschillende soorten time-outs die we kunnen instellen voor de OkHttp-client.

Raadpleeg onze inleidende OkHttp-gids voor het meer algemene overzicht van de OkHttp-bibliotheek.

2. Time-out verbinding

Een verbinding-time-out definieert een tijdsperiode waarin onze klant een verbinding tot stand moet brengen met een doelhost.

Standaard voor de OkHttpClient, is deze time-out ingesteld op 10 seconden.

We kunnen de waarde echter gemakkelijk wijzigen met de OkHttpClient.Builder # connectTimeout methode. Een waarde van nul betekent helemaal geen time-out.

Laten we nu kijken hoe we een OkHttpClient met een aangepaste time-out voor verbinding:

@Test openbare leegte whenConnectTimeoutExceeded_thenSocketTimeoutException () {OkHttpClient client = nieuwe OkHttpClient.Builder () .connectTimeout (10, TimeUnit.MILLISECONDS) .build (); Request request = nieuw Request.Builder () .url ("// 203.0.113.1") // niet routeerbaar adres .build (); Throwable gegooid = catchThrowable (() -> client.newCall (request) .execute ()); assertThat (gegooid) .isInstanceOf (SocketTimeoutException.class); }

Het bovenstaande voorbeeld laat zien dat de client een SocketTimeoutException wanneer de verbindingspoging de geconfigureerde time-out overschrijdt.

3. Time-out lezen

Een leestime-out wordt toegepast vanaf het moment dat de verbinding tussen een client en een doelhost tot stand is gebracht.

Het definieert een maximale tijd van inactiviteit tussen twee datapakketten tijdens het wachten op het antwoord van de server.

De standaard time-out van 10 seconden kan worden gewijzigd met OkHttpClient.Builder # readTimeout. Analoog aan de time-out voor de verbinding, geeft een nulwaarde geen time-out aan.

Laten we nu eens kijken hoe we in de praktijk een aangepaste leestime-out kunnen configureren:

@Test openbare leegte whenReadTimeoutExceeded_thenSocketTimeoutException () {OkHttpClient client = nieuwe OkHttpClient.Builder () .readTimeout (10, TimeUnit.MILLISECONDS) .build (); Request request = nieuwe Request.Builder () .url ("// httpbin.org/delay/2") // 2 seconden reactietijd .build (); Throwable gegooid = catchThrowable (() -> client.newCall (request) .execute ()); assertThat (gegooid) .isInstanceOf (SocketTimeoutException.class); }

Zoals we kunnen zien, retourneert de server het antwoord niet binnen de gedefinieerde time-out van 500 ms. Als gevolg hiervan is het OkHttpClient gooit een SocketTimeoutException.

4. Time-out schrijven

Een schrijftime-out definieert een maximale tijd van inactiviteit tussen twee datapakketten bij het verzenden van het verzoek naar de server.

Evenzo, wat betreft de verbinding en uitleestime-outs, we kunnen de standaardwaarde van 10 seconden overschrijven met OkHttpClient.Builder # writeTimeout. Als afspraak betekent een nulwaarde helemaal geen time-out.

In het volgende voorbeeld hebben we een zeer korte schrijf-time-out van 10 ms ingesteld en een inhoud van 1 MB op de server gepost:

@Test openbare leegte whenWriteTimeoutExceeded_thenSocketTimeoutException () {OkHttpClient client = nieuwe OkHttpClient.Builder () .writeTimeout (10, TimeUnit.MILLISECONDS) .build (); Request request = nieuw Request.Builder () .url ("// httpbin.org/delay/2") .post (RequestBody.create (MediaType.parse ("text / plain"), create1MBString ())) .build ( ); Throwable gegooid = catchThrowable (() -> client.newCall (request) .execute ()); assertThat (gegooid) .isInstanceOf (SocketTimeoutException.class); }

Zoals we zien, kan onze client vanwege de grote payload geen verzoektekst naar de server sturen binnen de gedefinieerde time-out. Bijgevolg is het OkHttpClient gooit een SocketTimeoutException.

5. Time-out voor oproep

Een time-out voor een oproep is een beetje anders dan de time-outs voor verbinden, lezen en schrijven die we al hebben besproken.

Het definieert een tijdslimiet voor een volledige HTTP-aanroep. Dit omvat het oplossen van DNS, verbinding maken, de hoofdtekst van het verzoek schrijven, serververwerking en het lezen van de antwoordtekst.

In tegenstelling tot andere time-outs, de standaardwaarde is ingesteld op nul, wat geen time-out impliceert. Maar we kunnen natuurlijk een aangepaste waarde configureren met OkHttpClient.Builder # callTimeout methode.

Laten we eens kijken naar een praktisch gebruiksvoorbeeld:

@Test openbare leegte whenCallTimeoutExceeded_thenInterruptedIOException () {OkHttpClient client = nieuwe OkHttpClient.Builder () .callTimeout (1, TimeUnit.SECONDS) .build (); Request request = nieuwe Request.Builder () .url ("// httpbin.org/delay/2") .build (); Throwable gegooid = catchThrowable (() -> client.newCall (request) .execute ()); assertThat (gegooid) .isInstanceOf (InterruptedIOException.class); }

Zoals we kunnen zien, is de time-out voor het gesprek overschreden en is de OkHttpClient gooit een InterruptedIOException.

6. Time-out per verzoek

Het wordt aanbevolen om een ​​single te maken OkHttpClient instantie en hergebruik het voor alle HTTP-aanroepen in onze applicatie.

Soms weten we echter dat een bepaald verzoek meer tijd kost dan alle andere. In deze situatie moeten we verleng een bepaalde time-out alleen voor dat specifieke gesprek.

In dergelijke gevallen kunnen we een OkHttpClient # newBuilder methode. Dit bouwt een nieuwe client op met dezelfde instellingen. We kunnen dan de builder-methoden gebruiken om de time-outinstellingen naar behoefte aan te passen.

Laten we nu eens kijken hoe we dit in de praktijk kunnen doen:

@Test openbare leegte whenPerRequestTimeoutExtended_thenResponseSuccess () gooit IOException {OkHttpClient defaultClient = nieuwe OkHttpClient.Builder () .readTimeout (1, TimeUnit.SECONDS) .build (); Request request = nieuwe Request.Builder () .url ("// httpbin.org/delay/2") .build (); Throwable gegooid = catchThrowable (() -> defaultClient.newCall (request) .execute ()); assertThat (gegooid) .isInstanceOf (InterruptedIOException.class); OkHttpClient extendedTimeoutClient = defaultClient.newBuilder () .readTimeout (5, TimeUnit.SECONDS) .build (); Antwoordantwoord = extendedTimeoutClient.newCall (verzoek) .execute (); assertThat (response.code ()). isEqualTo (200); }

Zoals we zien defaultClient kan de HTTP-oproep niet voltooien vanwege de overschreden leestime-out.

Daarom hebben we het extendedTimeoutClient, heeft de time-outwaarde aangepast en het verzoek met succes uitgevoerd.

7. Samenvatting

In dit artikel gaan we verschillende time-outs onderzocht die we kunnen configureren voor de OkHttpClient.

We hebben ook kort beschreven wanneer de verbinding-, lees- en schrijftime-outs worden toegepast tijdens een HTTP-oproep.

Bovendien, we hebben laten zien hoe gemakkelijk het is om een ​​bepaalde time-outwaarde voor slechts één verzoek te wijzigen.

Zoals gewoonlijk zijn alle codevoorbeelden beschikbaar op GitHub.