12 Replies Latest reply: Feb 26, 2011 7:46 PM by jschellSomeoneStoleMyAlias RSS

    Doubt Regarding HttpURLConnection (no of concurrent connections)

    801188
      Is there any limitation to no of concurrent connections that can be opened using HttpURLConnection ?
      I want to send Data to a servlet using HttpURLConnection . so I am starting 30 threads(to simulate concurrency ) and inside run i am opening HttpURLConnection and send data using post and receive response and closing the connection .But i am getting below error
      java.net.BindException: Address already in use: connect
           at java.net.PlainSocketImpl.socketConnect(Native Method)
           at java.net.PlainSocketImpl.doConnect(Unknown Source)
           at java.net.PlainSocketImpl.connectToAddress(Unknown Source)
           at java.net.PlainSocketImpl.connect(Unknown Source)
           at java.net.Socket.connect(Unknown Source)
           at java.net.Socket.connect(Unknown Source)
           at sun.net.NetworkClient.doConnect(Unknown Source)
           at sun.net.www.http.HttpClient.openServer(Unknown Source)
           at sun.net.www.http.HttpClient.openServer(Unknown Source)
           at sun.net.www.http.HttpClient.<init>(Unknown Source)
           at sun.net.www.http.HttpClient.New(Unknown Source)
           at sun.net.www.http.HttpClient.New(Unknown Source)
           at sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(Unknown Source)
           at sun.net.www.protocol.http.HttpURLConnection.plainConnect(Unknown Source)
           at sun.net.www.protocol.http.HttpURLConnection.connect(Unknown Source)
           at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(Unknown Source)
        • 1. Re: Doubt Regarding HttpURLConnection (no of concurrent connections)
          Kayaman
          Maybe you have a concurrency issue.

          What does your code look like?
          • 2. Re: Doubt Regarding HttpURLConnection (no of concurrent connections)
            801188
            From main i am starting threads as shown below.
                 
                      for(int i=0;i < =30 ;i++){
                                 new Worker(request).start();                              
                                                          }     
                 run method of my worker class looks like this
            public void run(){
                           HttpURLConnection httpURLConnection = null;
                           BufferedReader bReader = null;
                           BufferedWriter bWriter = null;
                           try {
            
                                //Some encryption to request
                                System.out.println("request ::" + request);
                                long startTime=System.currentTimeMillis();
                                httpURLConnection = (HttpURLConnection)gatewayURL.openConnection();
                                httpURLConnection.setDoOutput(true);
                                bWriter = new BufferedWriter(new OutputStreamWriter(
                                          httpURLConnection.getOutputStream(), "UTF-8"));
                                bWriter.write(request);
                                bWriter.flush();
                                bReader = new BufferedReader(new InputStreamReader(
                                          httpURLConnection.getInputStream()));
                                String line;
                                StringBuilder responseBuilder = new StringBuilder();
                                while ((line = bReader.readLine()) != null) {
                                     responseBuilder.append(line);
                                }
                                
                                System.out.println(String.format("%7d ,"+getMethodName(request)+" \n",new Object[]{(System.currentTimeMillis()-startTime)}));
                                System.out.println("response ::" + responseBuilder.toString());
                                responseBuilder = null;
                           } catch (KeyException e) {
                                System.err.println("KeyException   :: ", e);
            
                           } catch (UnsupportedEncodingException e) {
                                System.err.println("UnsupportedEncodingException  in " +
                                          "  :: ",e);
            
                           } catch (Exception e) {
                                e.printStackTrace(System.err);
                                System.err.println("Exception  :: ", e);
            
                           } finally {
                                if (httpURLConnection != null) {
                                     httpURLConnection.disconnect();
                                     httpURLConnection = null;
                                }
                                close(bReader);
                                close(bWriter);
                           }
            • 3. Re: Doubt Regarding HttpURLConnection (no of concurrent connections)
              EJP
              Is there any limitation to no of concurrent connections that can be opened using HttpURLConnection ?
              There is a practical limit as to the number of outbound socket connections you can create. When you use more than the available number within a two minute period you get this exception. This usually arises olnly during this kind of load simulation. All it means is that you aren't simulating a realistic load as far as the client is concerned. Reduce the number of connections until it stops happening. If you are calling HttpURLConnection.disconnect(), don't - this disables connection pooling which is another mitigation of this problem.
              • 4. Re: Doubt Regarding HttpURLConnection (no of concurrent connections)
                801188
                Hi EJP,
                I reduced the no of active concurrent connections to 10 through a Semaphore .now i am not getting that BindException.
                I defined a semaphore in WorkerManager class .
                public volatile Semaphore semaphore =new Semaphore(10,true);
                Using semaphore i am restricting the concurrent threads opening HttpURLConnection at a time only 10 threads can open connection.
                Is this the right approach?Can you please suggest an alternate best practice for the above?
                All it means is that you aren't simulating a realistic load as far as the client is concerned
                For a simple servlet how to simulate 50 concurrent users?

                Thanks for your help.
                • 5. Re: Doubt Regarding HttpURLConnection (no of concurrent connections)
                  EJP
                  Is this the right approach?
                  It's good enough.
                  Can you please suggest an alternate best practice for the above?
                  Why? You have one that works.
                  All it means is that you aren't simulating a realistic load as far as the client is concerned
                  For a simple servlet how to simulate 50 concurrent users?
                  With multiple test client hosts.
                  • 6. Re: Doubt Regarding HttpURLConnection (no of concurrent connections)
                    jduprez
                    Hello ejp,
                    All it means is that you aren't simulating a realistic load as far as the client is concerned
                    For a simple servlet how to simulate 50 concurrent users?
                    With multiple test client hosts.
                    Which has costly implications for what looks like a "cheap and dirty" load test tool (I've been through this before, and you happened to have helped me already).
                    Wouldn't it be realistic enough to have distinct client processes (JVMs) on a single host?

                    In terms of testing the server behavior, as soon as each client establish a specific socket, does that make any difference for the server if those distinct sockets originates from the same host vs if those sockets come from distinct hosts?

                    Regards,

                    J.
                    • 7. Re: Doubt Regarding HttpURLConnection (no of concurrent connections)
                      jduprez
                      EJP wrote:
                      Is there any limitation to no of concurrent connections that can be opened using HttpURLConnection ?
                      There is a practical limit as to the number of outbound socket connections you can create. When you use more than the available number within a two minute period you get this exception. This usually arises olnly during this kind of load simulation.
                      For more details about this 2mn period, by EJP himself, see that old thread: {message:id=4635861} (where I describe a very similar problem, except that my code had no grip on the HttpURLConnection instance, that were hidden by an intermediate layer).
                      That topic is full of misconceptions on my part, but ejp corrected them with several explanations on socket lifecycle and network settings.
                      • 8. Re: Doubt Regarding HttpURLConnection (no of concurrent connections)
                        EJP
                        Wouldn't it be realistic enough to have distinct client processes (JVMs) on a single host?
                        No. You will still get port exhaustion.
                        In terms of testing the server behavior, as soon as each client establish a specific socket, does that make any difference for the server if those distinct sockets originates from the same host vs if those sockets come from distinct hosts?
                        No difference apart from the reduced concurrency due to not having all those CPUs. But that's not his problem. His problem is local port exhaustion at the test client host.
                        • 9. Re: Doubt Regarding HttpURLConnection (no of concurrent connections)
                          jduprez
                          EJP wrote:
                          Wouldn't it be realistic enough to have distinct client processes (JVMs) on a single host?
                          No. You will still get port exhaustion.
                          Yes, I got that. I thought you might be referring to something else.
                          At the time of my own problems, you were frowning at my attempts to simulate concurrent clients from a single host; you made it clear that local ports problems were artifacts of the "unrealistic" simulation. You also pointed out that connection pooling was also changing the game (which happens by default within one single JVM process if the target server speaks HTTP 1.1).

                          Here is the kind of "something else" I thought you might imply:
                          No difference apart from the reduced concurrency due to not having all those CPUs.
                          Edited by: jduprez on Feb 23, 2011 12:13 PM
                          • 10. Re: Doubt Regarding HttpURLConnection (no of concurrent connections)
                            jduprez
                            But that's not his problem. His problem is local port exhaustion at the test client host.
                            Yes. Going back to that, isn't it surprising to witness the bind exception with only 30 virtual clients?
                            Given the code of the run() method above, this should make at most only 30 concurrent sockets (and maybe less, if the HttpUrlConnection instances share an underlying socket: http://download.oracle.com/javase/6/docs/api/java/net/HttpURLConnection.html).

                            Of course we don't know what other softwares may be running on his client host, and we see only a fraction of the code.

                            At the time of my own problems, my Windows host's netstat -a exhibited only 300 sockets, which should have left plenty of rooms for more sockets before running out of ~5000 local ports (as per Windows docs).
                            • 11. Re: Doubt Regarding HttpURLConnection (no of concurrent connections)
                              801188
                              Hi jduprez ,EJP

                              Thanks for your sharing your ideas.
                              Of course we don't know what other softwares may be running on his client host, and we see only a fraction of the code.
                              My main loop looks like as below
                                                  for (Map.Entry<String, List<String>> userDetails : paramCache
                                                            .entrySet()) {
                                                       requestNo=0;
                                                       randomGen = new Random();
                                                       for (String request : requestCache) {
                                                            request = request.replaceAll("KEY", entry.getKey());
                                                            request = request.replaceAll("KEY_ONE", userDetails
                                                                      .getValue().get(
                                                                                randomGen.nextInt(userDetails.getValue()
                                                                                          .size())));
                                                            request = request.replaceAll("KEY_TWO", userDetails
                                                                      .getKey());
                                                            System.out.println("MODIFIED REQUEST ::" + request);
                                                            for(int i=0;i < 10 ;i++){
                                                                 processRequest(request);
                                                            }
                                                       }
                                                  }
                              one more outer for loop .In this case it will execute only one time .Size of my request cache is 20,Inner for loop execute 10 times ,Size of my paramCache is 2. So at max it will execute 400 times. From process request i am starting one thread it's run is shown above.I am trying this from a windows machine(windows XP OS with SP3).in processRequest what i am doing is Starting a worker. as shown below.
                              new Worker(request).start();
                              adding this workers to a collection .
                              after completion of loop i am invoking join on all workers.Starting above code from multiple hosts is the only way for testing large no of concurrent users?
                              • 12. Re: Doubt Regarding HttpURLConnection (no of concurrent connections)
                                jschellSomeoneStoleMyAlias
                                jduprez wrote:
                                But that's not his problem. His problem is local port exhaustion at the test client host.
                                Yes. Going back to that, isn't it surprising to witness the bind exception with only 30 virtual clients?
                                Given the code of the run() method above, this should make at most only 30 concurrent sockets (and maybe less, if the HttpUrlConnection instances share an underlying socket: http://download.oracle.com/javase/6/docs/api/java/net/HttpURLConnection.html).

                                Of course we don't know what other softwares may be running on his client host, and we see only a fraction of the code.

                                At the time of my own problems, my Windows host's netstat -a exhibited only 300 sockets, which should have left plenty of rooms for more sockets before running out of ~5000 local ports (as per Windows docs).
                                As EJP said in his first post "+...within a two minute period...+"