OkHttpClient com problema de operadora de celular
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:
- Funciona com WIFI = Sim
- Funciona com operadora Airtel = Sim
- Funciona com a operadora Jio = Sim
- Rede funciona em outros países = Sim
- Funciona em navegador móvel com a operadora Vodafone Idea = Sim
- 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
É 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.