0

I have observed that one of my api is taking much more time if called through Java (URLConnection or Apache Http Client or OKHttp) for the first time. For the subsequent calls, the time is much lesser.

Although Postman or curl.exe takes very less time(comparable to the second iterations of java)

Debug Run

For my machine, the first time overhead is around 2 secs. But on some machines this is rising to around 5-6 secs for the first time. Thereafter it is around 300 ms roundtrip.

Here is my sample code:

public static String DoPostUsingURLConnection(String s_uri) throws Exception {
        try {
            URL uri = new URL(s_uri);
            HttpURLConnection connection = (HttpURLConnection) uri.openConnection();
            // Logger.log("Opened Connection");
            connection.setRequestMethod("POST");
            connection.setRequestProperty("Content-Type", "application/json");
            connection.setDoOutput(true);

            connection.setRequestProperty("Authorization", authorizationHeader);

            // Create the Request Body
            try (OutputStream os = connection.getOutputStream()) {
                byte[] input = jsonRequestBody.getBytes("utf-8");
                os.write(input, 0, input.length);
            }

            // Logger.log("Written Output Stream");

            int responseCode = connection.getResponseCode();
            InputStream is = null;
            if (responseCode == HttpURLConnection.HTTP_OK)
                is = connection.getInputStream();
            else
                is = connection.getErrorStream();

            BufferedReader in = new BufferedReader(new InputStreamReader(is));
            String inputLine;
            StringBuffer response = new StringBuffer();

            while ((inputLine = in.readLine()) != null) {
                response.append(inputLine).append("\n");
                ;
            }
            in.close();

            return response.toString();

        } catch (Exception ex) {
            return ex.getMessage();
        } finally {
            // Logger.log("Got full response");
        }
  • It might be caused by HTTPS CRL check. – vbezhenar Jan 12 '22 at 13:57
  • I suspected it, and tried to turn off ssl-validation https://stackoverflow.com/questions/1201048/allowing-java-to-use-an-untrusted-certificate-for-ssl-https-connection, but still the overhead is too much in case of Java with all the three libraries. PostMan & Curl must be doing ssl validation as well, but none takes so much time for creating the connection – Anshuman Chatterjee Jan 13 '22 at 03:45

2 Answers2

1

You can investigate where time is taken by logging OkHttp connections events. https://square.github.io/okhttp/events/

It will be particularly relevant if you are getting an IPv4 address and IPv6 and one is timing out and the other one succeeding.

Yuri Schimke
  • 12,435
  • 3
  • 35
  • 69
  • I have checked the events and found out that creating the okhttpclient is taking more than 5secs. Similar is with all other clients. I suspect this is something to do with the particular java/system config. https://imgur.com/QVV1Dby – Anshuman Chatterjee Jan 24 '22 at 11:38
  • It's probably worth grabbing a snapshot at this point. This should be very cheap. IT could be init of the crypto and certificate code. Any chance you are doing a lot of customisation of the trust manager? loading certificates? – Yuri Schimke Jan 24 '22 at 14:54
0

This is just a guess. But the way Http connection works, that when you invoke it for the first time the connection gets established and that takes time. After that Http protocol doesn't really close connection for some time in expectation that some more requests would come and the connection could be re-used. And in your case indeed you send subsequent requests that re-use the previously created connection rather then re-establishing it which is expansive. I have written my own Open Source library that has a simplistic Http client in it. I noticed the same effect that first request takes much longer time than subsequent requests. But that doesn't explain why in Postman and curl we don't see the same effect. Anyway, if you want to solve this problem and you know your URL in advance, send a request upon your app initialization (you can even do it in separate thread). That will solve your problem.

If you are interested to look at my library here is Javadoc link. You can find it as maven artifact here and on github here. Article about the library covering partial list of features here

Michael Gantman
  • 7,315
  • 2
  • 19
  • 36
  • 1
    This, plus happy eyeballs. That's a spec where the HTTP client works around bad IPv6 deployments by falling back to IPv4 sooner. We're currently implementing it in OkHttp. – Jesse Wilson Jan 12 '22 at 17:23
  • I will try with your library for sure. I am aware that the subsequent connection can be pooled, ssl-validation can be skipped. Still I raised this question because the overheads of ssl-validation, connection establishment etc must also be with PostMan & cURL. But for java, it is significantly more. @JesseWilson might be correct. It could be due to trials towards IPv6. – Anshuman Chatterjee Jan 13 '22 at 03:48