Solução para SocketTimeoutException em Requisições com OkHttp no Java

Ao raelizar uma chamada de API localmente utilizando o OkHttpClient, você pode encontrar erros de timeout, como indicado nos registros de exceção abaixo:

Exception in thread "main" java.net.SocketTimeoutException: timeout
    at okio.Okio$4.newTimeoutException(Okio.java:230)
    at okio.AsyncTimeout.exit(AsyncTimeout.java:285)
    at okio.AsyncTimeout$2.read(AsyncTimeout.java:241)
    at okio.RealBufferedSource.indexOf(RealBufferedSource.java:345)
    at okio.RealBufferedSource.readUtf8LineStrict(RealBufferedSource.java:217)
    at okio.RealBufferedSource.readUtf8LineStrict(RealBufferedSource.java:211)
    at okhttp3.internal.http1.Http1Codec.readResponseHeaders(Http1Codec.java:189)
    at okhttp3.internal.http.CallServerInterceptor.intercept(CallServerInterceptor.java:75)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
    ... (mais 20 linhas)

Caused by: java.net.SocketTimeoutException: Read timed out
    at java.net.SocketInputStream.socketRead0(Native Method)
    at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
    at java.net.SocketInputStream.read(SocketInputStream.java:171)
    at java.net.SocketInputStream.read(SocketInputStream.java:141)
    at okio.Okio$2.read(Okio.java:139)
    at okio.AsyncTimeout$2.read(AsyncTimeout.java:237)
    ... (mais 21 linhas)

A causa raiz deste problema é frequentemente que o processamento da API no servidor demora mais do que o tempo de resposta que o cliente está disposto a esperar. Para resolver, é necessário configurar os tempos de timeout do OkHttpClient para valores mais adequados. Aumentar os limites de conexão e leitura para 50 segundos, por exemplo, pode resolver o problema. Veja o código a seguir:

int tempoLimite = 50000; // milissegundos
OkHttpClient httpClient = new OkHttpClient.Builder()
        .connectTimeout(tempoLimite, TimeUnit.MILLISECONDS)
        .readTimeout(tempoLimite, TimeUnit.MILLISECONDS)
        .build();

Alguns desenvolvedores sugerem a configuração dos tempos de timeout usando métodos do tipo set diretamente na instância do cliente, como mostrado no exemplo abaixo:

OkHttpClient client = new OkHttpClient();
client.setConnectTimeout(30, TimeUnit.SECONDS); // tempo de conexão
client.setReadTimeout(30, TimeUnit.SECONDS);    // tempo de leitura do socket

No entanto, tal abordagem não é suportada pela API atual do OkHttp. A classe OkHttpClient é projetada como imutável; suas configurações são definidas no momento da construção e não podem ser alteradas posteriormente. Portanto, a utilização do Builder é o método correto e recomendado para definir os tempos de timeout.

Tags: OkHttp java SocketTimeoutException Requisições HTTP Timeout de Rede

Publicado em 6-18 08:23