OkHttpClient with Mobile Carrier issue

Viewed 494

My Application API perform weird behavior. One of my live app's api expected response time 2 to 3 seconds but it takes long time to response!

Test Cases:

  1. Works with WIFI = Yes
  2. Works with Airtel carrier = Yes
  3. Works with Jio carrier = Yes
  4. Works in Other countries network =Yes
  5. Works in mobile browser with Vodafone Idea carrier = Yes
  6. Works with Same API with IOS app using Vodafone Idea carrier = Yes

Main Issue: Issue with Vodafone Idea carrier using App = Very Slow

Case1.

 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);
                }

Outcome:

  • First time 40 to 50 seconds.
  • On every next consecutive call it will return within 2 to 5 seconds as per expectation.

Case 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());
            }
        });

Outcome:

  • Every time takes 40 to 50 seconds.

Case 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());
                }
            });

Outcome:

  • Every time it takes 5 to 6 seconds.

Note: I am afraid to use .connectTimeout(1, TimeUnit.SECONDS) as 1 second in app It started to give more api failure and not looks correct solution as well.

Update CaseStudy:

https://github.com/square/okhttp Detail debug of OkHttpClient. it gives below error 4 times approx.
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  

package okhttp3.internal.connection.RealConnection class. trying to establish connectSocket but getting error.

-> After adding "www" www.example.com into my domain. Response time change from 40 seconds to 12 seconds approx for okhttp library.

1 Answers

It is hard to see the whole picture because you don't explain how you execute the subsequent connections. It is entirely possible that you are reusing an existing connection. By default, HTTP/1.1 keeps connections alive.

Checking to see if using plain-text HTTP vs. HTTPS makes a difference could be interesting, too, as the connection setup cost is higher with HTTPS. Your client may also do more verification based on the certificate that is returned.

If changing the hostname makes so much difference, then I would definitely look at how the name resolver is configured on the system.

I would also capture network traffic and see what is taking long. tcpdump is your friend or you could always consider using wireshark

As others have suggested, you may also want to disable the IPv6 stack on the box to rule out as the source of the problem.

Related