OkHttpClient с проблемой оператора мобильной связи

#android #tcp #socket.io #httpurlconnection #okhttp

#Android #tcp #socket.io #httpurlconnection #okhttp

Вопрос:

Мой API приложения ведет себя странно. Ожидаемое время отклика одного из API моего приложения Live от 2 до 3 секунд, но для ответа требуется много времени!

Тестовые примеры:

  1. Работает с WIFI = Да
  2. Работает с оператором Airtel = Да
  3. Работает с оператором Jio = Да
  4. Работает в сети других стран = Да
  5. Работает в мобильном браузере с оператором Vodafone Idea = Да
  6. Работает с тем же API, что и приложение для IOS, используя оператора Vodafone Idea = Да

Основная проблема: проблема с оператором Vodafone Idea, использующим приложение = очень медленно

Случай 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);
                }
  

Результат:

  • Первый раз от 40 до 50 секунд.
  • При каждом следующем последовательном вызове он будет возвращаться в течение 2-5 секунд в соответствии с ожиданиями.

Случай 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());
            }
        });
  

Результат:

  • Каждый раз занимает от 40 до 50 секунд.

Случай 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());
                }
            });
  

Результат:

  • Каждый раз это занимает от 5 до 6 секунд.

Примечание: я боюсь использовать .ConnectTimeout(1, TimeUnit.СЕКУНДЫ) через 1 секунду в приложении он начал давать больше сбоев api и также не выглядит правильным решением.

Обновить CaseStudy:

https://github.com/square/okhttp Подробная отладка OkHttpClient. он выдает ошибку ниже примерно в 4 раза.

 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  
  

пакет okhttp3.internal.connection.Класс RealConnection.
пытаюсь установить connectSocket, но получаю ошибку.

-> После добавления «www»www.example.com в мой домен. Изменение времени отклика с 40 секунд до 12 секунд приблизительно для библиотеки okhttp.

Комментарии:

1. Вы должны собрать некоторые события с помощью прослушивателя и добавить их в свой вопрос square.github.io/okhttp/events

2. @YuriSchimke Спасибо. Добавлено исключение во время отладки. Пожалуйста, обратите внимание, что проблема возникает только в 1 конкретной сети!

3. В моем приложении также есть Google Cloud Engine для сервера и использования хранилища firebase и облачных функций @YuriSchimke

4. Интересная проблема, но я боюсь, что мы упускаем полную картину. Может быть, вы создаете действительно много других подключений в своем приложении? Я не думаю, что этот приведенный вами код сможет воспроизвести проблему, которую вы описываете, сам по себе, поэтому создание минимально воспроизводимого примера очень помогло бы.

5. В вашем сообщении указан IPv6-адрес. Используют ли сценарии, которые работают быстрее, IPv4 или IPv6?

Ответ №1:

Трудно увидеть всю картину, потому что вы не объясняете, как вы выполняете последующие подключения. Вполне возможно, что вы повторно используете существующее соединение. По умолчанию HTTP / 1.1 поддерживает активные соединения.

Проверка того, имеет ли значение использование обычного текста HTTP по сравнению с HTTPS, также может быть интересной, поскольку стоимость настройки соединения с HTTPS выше. Ваш клиент также может выполнить дополнительную проверку на основе возвращаемого сертификата.

Если изменение имени хоста имеет такое большое значение, то я бы обязательно посмотрел, как в системе настроен распознаватель имен.

Я бы также зафиксировал сетевой трафик и посмотрел, что занимает много времени. tcpdump — ваш друг, или вы всегда можете рассмотреть возможность использования wireshark

Как предлагали другие, вы также можете отключить стек IPv6 в окне, чтобы исключить источник проблемы.

Комментарии:

1. я посоветовался со своими товарищами по команде, которые обладают хорошими знаниями на сетевом уровне, мы обнаружили, что даже «трассировка маршрута <<Домен>>» в терминале занимает слишком много времени! В заключение. я использовал «HttpsURLConnection» и в первый раз сохраняю setConnectTimeout в течение 1 секунды. для любых других следующих вызовов это будет обычный тайм-аут!

2. трассировка маршрута может вводить в заблуждение, особенно если вы используете имя хоста вместо IP-адреса. Некоторое сетевое оборудование также может блокировать некоторый трафик. Ваш лучший выбор — анализатор сетевого трафика.