OkHttpClient com problema de operadora de celular

Aug 28 2020

Minha API de aplicativo executa um comportamento estranho. O tempo de resposta esperado de uma das APIs do meu aplicativo ao vivo é de 2 a 3 segundos, mas a resposta demora muito!

Casos de teste:

  1. Funciona com WIFI = Sim
  2. Funciona com operadora Airtel = Sim
  3. Funciona com a operadora Jio = Sim
  4. Rede funciona em outros países = Sim
  5. Funciona em navegador móvel com a operadora Vodafone Idea = Sim
  6. Funciona com a mesma API com o aplicativo IOS usando a operadora Vodafone Idea = Sim

Problema principal: Problema com a operadora Vodafone Idea usando App = Muito lento

Caso 1.

 URL url = new URL("https://example.com");
                urlConnection = (HttpsURLConnection) url.openConnection();
                urlConnection.setReadTimeout(10000);
                urlConnection.setConnectTimeout(10000);
                int code = urlConnection.getResponseCode();
                if (code !=  200) {
                    throw new IOException("Invalid response from server: " + code);
                }

                BufferedReader rd = new BufferedReader(new InputStreamReader(
                        urlConnection.getInputStream()));
                String line;
                while ((line = rd.readLine()) != null) {
                    Log.e("data", line);
                }

Resultado:

  • Primeira vez de 40 a 50 segundos.
  • Em cada chamada consecutiva seguinte, ele retornará dentro de 2 a 5 segundos conforme a expectativa.

Caso 2:

OkHttpClient okHttpClient = new OkHttpClient.Builder().build();

        Request.Builder requestBuilder = new Request.Builder()
                .url("https://example.com")
                .addHeader("Content-Type", "application/json");
        Request request = requestBuilder.build();
        Log.e("APi", "REQUEST: "+request.toString());

        Call call1 = okHttpClient.newCall(request);
        call1.enqueue(new Callback() {
            @Override
            public void onFailure(@NotNull Call call, @NotNull IOException e) {
                Log.e("APi", "APi Failed");
            }

            @Override
            public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
                Log.e("APi", "APi isSuccessful:" + response.isSuccessful());
                Log.e("APi", "Response:" + response.body().string());
            }
        });

Resultado:

  • Cada vez leva de 40 a 50 segundos.

Caso 3:

    OkHttpClient okHttpClient = new OkHttpClient.Builder()
.connectTimeout(1, TimeUnit.SECONDS).build();
    
            Request.Builder requestBuilder = new Request.Builder()
                    .url("https://example.com")
                    .addHeader("Content-Type", "application/json");
            Request request = requestBuilder.build();
            Log.e("APi", "REQUEST: "+request.toString());
    
            Call call1 = okHttpClient.newCall(request);
            call1.enqueue(new Callback() {
                @Override
                public void onFailure(@NotNull Call call, @NotNull IOException e) {
                    Log.e("APi", "APi Failed");
                }
    
                @Override
                public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
                    Log.e("APi", "APi isSuccessful:" + response.isSuccessful());
                    Log.e("APi", "Response:" + response.body().string());
                }
            });

Resultado:

  • Cada vez, leva de 5 a 6 segundos.

Nota: Estou com medo de usar .connectTimeout (1, TimeUnit.SECONDS) como 1 segundo no aplicativo. Ele começou a dar mais falha de API e não parece a solução correta também.

Atualizar estudo de caso:

https://github.com/square/okhttp Depuração detalhada de OkHttpClient. dá o erro abaixo 4 vezes aprox.
failed to connect to xxx.com/2001:4860:4802:36::15 (port XXX) from /2402:3a80:1b8f:ca21:847:21a8:5ffc:fc30 (port XXX) after 10000ms  

pacote okhttp3.internal.connection.RealConnection class. tentando estabelecer connectSocket, mas obtendo erro.

-> Depois de adicionar "www" www.example.com ao meu domínio. O tempo de resposta muda de 40 segundos para 12 segundos aproximadamente para a biblioteca okhttp.

Respostas

1 BertoldKolics Sep 07 2020 at 03:40

É difícil ver o quadro completo porque você não explica como executa as conexões subsequentes. É perfeitamente possível que você esteja reutilizando uma conexão existente. Por padrão, HTTP / 1.1 mantém as conexões ativas.

Verificar se o uso de HTTP de texto simples vs. HTTPS faz diferença também pode ser interessante, pois o custo de configuração da conexão é maior com HTTPS. Seu cliente também pode fazer mais verificações com base no certificado que é devolvido.

Se alterar o nome do host faz tanta diferença, então eu definitivamente examinaria como o resolvedor de nomes está configurado no sistema.

Gostaria também de capturar o tráfego da rede e ver o que está demorando. O tcpdump é seu amigo ou você pode sempre considerar o uso de WireShark

Como outros sugeriram, você também pode desativar a pilha IPv6 na caixa para descartar como a origem do problema.