OkHttpClient z problemem z operatorem komórkowym
Moje API aplikacji działa dziwnie. Oczekiwany czas odpowiedzi jednego z interfejsów API mojej aplikacji na żywo to 2 do 3 sekund, ale odpowiedź zajmuje dużo czasu!
Przypadki testowe:
- Działa z WIFI = Tak
- Współpracuje z przewoźnikiem Airtel = Tak
- Działa z nośnikiem Jio = Tak
- Działa w sieci innych krajów = Tak
- Działa w przeglądarce mobilnej z nośnikiem Vodafone Idea = Tak
- Działa z Same API z aplikacją IOS przy użyciu nośnika Vodafone Idea = Tak
Główny problem: problem z nośnikiem Vodafone Idea używającym aplikacji = bardzo wolno
Przypadek 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);
}
Wynik:
- Pierwszy raz 40 do 50 sekund.
- Przy każdym kolejnym połączeniu powróci w ciągu 2 do 5 sekund zgodnie z oczekiwaniami.
Przypadek 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());
}
});
Wynik:
- Za każdym razem trwa od 40 do 50 sekund.
Przypadek 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());
}
});
Wynik:
- Za każdym razem zajmuje to od 5 do 6 sekund.
Uwaga: boję się używać .connectTimeout (1, TimeUnit.SECONDS) jako 1 sekundę w aplikacji. Zaczęło to dawać więcej błędów API i również nie wygląda na poprawne rozwiązanie.
Zaktualizuj CaseStudy:
https://github.com/square/okhttp Szczegóły debugowania OkHttpClient. poniżej daje błąd 4 razy ok.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
pakiet okhttp3.internal.connection.RealConnection, klasa. próbuję ustanowić connectSocket, ale pojawia się błąd.
-> Po dodaniu „www” www.example.com do mojej domeny. Czas odpowiedzi zmienia się z 40 sekund do około 12 sekund dla biblioteki okhttp.
Odpowiedzi
Trudno jest zobaczyć cały obraz, ponieważ nie wyjaśniasz, w jaki sposób wykonujesz kolejne połączenia. Jest całkowicie możliwe, że ponownie używasz istniejącego połączenia. Domyślnie HTTP / 1.1 utrzymuje połączenia przy życiu.
Sprawdzenie, czy użycie zwykłego tekstu HTTP w porównaniu z HTTPS ma znaczenie, może być również interesujące, ponieważ koszt konfiguracji połączenia jest wyższy w przypadku HTTPS. Twój klient może również przeprowadzić dokładniejszą weryfikację na podstawie zwróconego certyfikatu.
Jeśli zmiana nazwy hosta robi tak dużą różnicę, to zdecydowanie przyjrzałbym się, jak skonfigurowany jest program rozpoznawania nazw w systemie.
Przechwyciłbym również ruch w sieci i zobaczył, co trwa długo. tcpdump to twój przyjaciel lub zawsze możesz rozważyć użycie wireshark
Jak sugerowali inni, możesz również chcieć wyłączyć stos IPv6 na pudełku, aby wykluczyć jako źródło problemu.