We're facing a /serious /issue with the non-native AJP connector.

To put it most simply, some requests seem to "get lost" in Tomcat in various cases involving concurrent requests -- and not egregious numbers of concurrent requests, either.

For instance,

  1. Use a Tomcat 5.5.23 with a configuration like:

       <Connector port="8010"
                  minSpareThreads="4" maxSpareThreads="12"
   maxThreads="18" acceptCount="282"
                  tomcatAuthentication="false"
   useBodyEncodingForURI="true" URIEncoding="UTF-8"
                  enableLookups="false" redirectPort="8443"
   protocol="AJP/1.3" />

   (which are intended solely for making it easier to test concurrency
   issues that to overrun a realistic 'maxThreads' setting) and as a
   control, similar thread pool settings on the direct HTTP connector:

       <Connector port="8080" maxHttpHeaderSize="8192"
                  minSpareThreads="4" maxSpareThreads="12"
   maxThreads="18" acceptCount="282"
                  enableLookups="false" redirectPort="8443"
                  connectionTimeout="20000" disableUploadTimeout="true" />

  2. Use an Apache 2.2.4 with mod_proxy_ajp with a configuration like:

       <Proxy balancer://ajpWorker>
       BalancerMember ajp://localhost:8010 min=16 max=300 smax=40
       ttl=900 keepalive=Off timeout=900
       </Proxy>

       RewriteEngine on
       RewriteRule ^(/TestApp/(.*\.jsp(.*)|servlet/.*|.*\.jar))$
       balancer://ajpWorker$1 [P]

   (on Windows in this case; similar results can be obtained on Linux
   at least)

  3. Use a simple test JSP page (placed in a web app containing nothing
     else):

       <[EMAIL PROTECTED] session="false"
       %><[EMAIL PROTECTED] contentType="text/html" pageEncoding="UTF-8"
       %><%!
         private static final String  titleString = "Sleepy Test JSP Page";
       %><html>
       <head>
       <%
         String  sleepSeconds = request.getParameter( "secs" );
         if ( sleepSeconds == null )
           sleepSeconds = "1";
         long  secsToSleep = Long.parseLong( sleepSeconds );
         Thread.sleep( 1000L * secsToSleep );
       %>
       <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
       <title><%=titleString%></title>
       </head>
       <body>
       <center>
       <h2><%=titleString%>: SUCCESS!</h2>
       [Slept <%= secsToSleep %> seconds.]
       </center>
       </body>
       </html>

  4. Hit the page with ab
         * First, test direct Tomcat connections:
               o ab -n 24 -c 24 -A wcadmin:wcadmin
                 http://hostname:*8080*/TestApp/test.jsp?secs=3
                     + Result: All requests complete sucessfully in
                       6118 ms.
         * Second, test connections via Apache:
               o ab -n 24 -c 24 -A wcadmin:wcadmin
                 http://hostname/TestApp/test.jsp?secs=3
                     + Result: Only 17 requests complete before ab
                       times out.
         * Third, test connections via Apache again soon (under the
           BalancerMember 'timeout' seconds) after the last test
               o ab -n 24 -c 24 -A wcadmin:wcadmin
                 http://hostname/TestApp/test.jsp?secs=3
                     + Result: Only 9 requests complete before ab times
                       out.

Something is clearly /horribly/ wrong with the handling of any concurrency over 'maxThreads' in this case. Even so, there seems to be some sort of "off-by-one" error in that only 17 requests complete, not 18. Worse, this has a lingering effect that decreases Tomcat's ability to concurrent requests thereafter (with this impact seemingly being much worse the longer the BalancerMember timeout is set to -- and we have some very long running requests and thus need this timeout to be /very/ large).

This is not the only ill effect we've seen when hitting Tomcat 5.5.24 with concurrent requests in this manner, but it is a good place to start.

As for the native connector, it just works here. So why don't I just use it? Well, first off, we have to support Tomcat on Windows (32 and 64-bit), Linux, Solaris, HPUX (PA-RISC and Itanium), and AIX. We've been unable to get the connector built on some of these platforms and on some we can't get the resulting binary to function (specifically on AIX). Further, we had some stability issues with the native connector in the past and had considered the Java connector the safest, if not fastest, option -- and to a degree given that everything is Java I still feel that's the case. Finally, however, this connector should just plain work. Tomcat shouldn't be a cripple unless/until you manage to build a native connector for your platform.

Any troubleshooting and/or debugging ideas (e.g. where exactly to place breakpoints, what logs to turn on, etc, etc) would be /greatly/ appreciated.

--
Jess Holle
[EMAIL PROTECTED]

P.S. If this should go to the user's mailing list instead that's fine, but this really seemed like a developer-oriented issue to me.

Reply via email to