Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-6238070

Unable to control keepalive time out in HttpUrlConnection

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Not an Issue
    • Icon: P4 P4
    • None
    • 5.0
    • core-libs
    • x86
    • windows_2000

      FULL PRODUCT VERSION :
      java version "1.5.0_01"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_01-b08
      Java HotSpot(TM) Client VM (build 1.5.0_01-b08, mixed mode, sharing)

      ADDITIONAL OS VERSION INFORMATION :
      Windows 2000 service pack 4

      A DESCRIPTION OF THE PROBLEM :
      I need to use Http 1.1 persistent connection capabilities of the class java.net.HttpUrlConnection to run my http client.
      My http client sends multiple requests to a servlet running in Tomcat 5.0.19 web server and after 5 sec it doesn't send a message the underlying socket is replaced with another socket (I'm using TCPView to view the state of the tcp sockets).
      In particular I need to estabilish 'long-lived' tcp connection but in this way it's not possible because I can't handle the keepAliveTimeOut.
      By analyzing the source code of HttpUrlConnection and related classes, and Tomcat connector, I've discovered that:
      -in the sun client classes, in the cases of 'noProxy', the keepAliveTimeOut is hardcoded and is 5 sec: but if it receives something like:
      "timeout=40, max=5" in the "Keep-Alive" header property it should take it into account; besides, it seems to be no limit about the number of requests I can do on the underlying socket
      -in Tomcat, setting the property maxKeepAliveRequests="-1", the socket is never closed by the web server, and the connectionTimeout="20000" doesn't create problems; besides it seems to be hardcoded a keepAliveTimeOut of 60 sec.





      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Simply execute the test methods with and without the codeblock surrounded by th line comments:
      //--------------
      ....
      //--------------

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Among client side and server side, the stronger keepAliveTimeOut constraint is the Tomcat constraint: connectionTimeout="20000";
      after this there is the "timeout=40... of the client, and so the 60 sec hardcoded in Tomcat.
      So, running the method 'request(false)' including the codeblock surrounded by th line comments:
      //--------------
      ....
      //--------------
      the socket should remain the same if i don't send a message in 20 sec (connectionTimeout="20000" )
      ACTUAL -
      the socket is replaced randomly; it is replaced much frequently if the frequency of the requests is higher;
      if I exclude the code inside the
      //--------------
      ....
      //--------------
      it is replaced after 5 sec if I send norequest

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      ==============CLIENT SIDE==============
        private synchronized void request(boolean close){
          try{
            con=(HttpURLConnection) url.openConnection();
            con.setDoInput(true);
            con.setDoOutput(true);
            con.setUseCaches(false);
            con.setRequestProperty("Content-Type", "application/octet-stream");

      //------------
            if(close)
              con.setRequestProperty("connection","close");
             else{
              con.setRequestProperty("connection","keep-alive");
              con.setRequestProperty("Keep-Alive", "timeout=40, max=5");
            }
      //---------

            ObjectOutputStream os=new ObjectOutputStream(con.getOutputStream());
            os.writeObject("xx");
            os.close();

            ObjectInputStream is = new ObjectInputStream(con.getInputStream());
            Object o = is.readObject();
            is.close();
          }
          catch (Exception e) {
            e.printStackTrace();
          }
        }
      ===================================

      ==============SERVER SIDE==========
      servlet with:

        protected void service(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws ServletException, IOException {

          String connHeader=httpServletRequest.getHeader("connection");
          if(connHeader!=null && connHeader.toLowerCase().equals("keep-alive")){
            String kaHeader=httpServletRequest.getHeader("Keep-Alive");
            if(kaHeader!=null){
              httpServletResponse.setHeader("Connection",connHeader);
              httpServletResponse.setHeader("Keep-Alive",kaHeader);
            }
          }

          ObjectInputStream is = new ObjectInputStream(httpServletRequest.getInputStream());
          Object o=null;
          try {o=is.readObject();}catch (Exception e) {e.printStackTrace();}
          is.close();

          ObjectOutputStream os = new ObjectOutputStream(httpServletResponse.getOutputStream());
          os.writeObject("tnx");
          os.close();
        }
      ===================================
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      I tried this workaround:
      -set the response header property ("Keep-Alive","timeout=40, max=5") in my server-side code, so to let the client side (class sun.net.www.http.HttpClient) read it;
      -set maxKeepAliveRequests="-1" in Tomcat;
      the things seem to work much better, but sometimes, unexpectedly, the tcp socket is replaced, also after 1-2 sec from the last mesage. Besides, after some minutes the client cpu raise to 90%
      ###@###.### 2005-03-09 09:36:42 GMT

            Unassigned Unassigned
            ndcosta Nelson Dcosta (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: