On 09/04/2021 11:53, Peter Chamberlain wrote:
Hello,
I've been trying to understand the behaviour of tomcat when handling
internal redirects. I'm testing using tomcat 9.0.38. I'm testing using
jdk8 1.8.0_265. My main test cases have been 2 forwards to the same
servlet, and then a response. Or 2 redirects to the same servlet and
then a response.

The forward case looks like a single HTTP request to both Tomcat and the client.

The redirect case looks like 3 separate HTTP requests to both Tomcat and the client. The first two receive a 302 response (no body) and finally a 200 response with a body. Depending on how the client and Tomcat are configured these requests may occur on a single network connection (HTTP keep-alive is enabled) or may require a separate connection for each request (HTTP keep-alive is disabled).

Once you get into the situation where the network layer is over-loaded, behaviour is very much system dependent. It will vary between operating systems and between major Java versions.

Note that the OS treats any accept count setting more as a guideline than a hard rule and may ignore it completely. Under heavy load you also often see other effects (such as port exhaustion impacting the results).

If the backlog is considered to be full, any subsequent connection attempts will will refused immediately.

Connection timeout is measured from when the server first tries to read the request. From that point the client has connectionTimeout to send the first byte.

NIO uses a Poller/Selector approach whereas NIO2 uses completion handlers. In many ways there isn't that much difference between them. I suspect that NIO will perform better on some systems and NIO2 on others.

When I have looked at this sort of thing in the past, the results have nearly always been skewed by other factors. Only by significantly reducing the number of client threads and Tomcat threads (less than 10 each) was I able to start to see the sort of behaviour expected around dropped connections, backlog etc and even then it took a fair amount of analysis to confirm that what I was observing was as expected.

Mark



 Servlet as follows:

@WebServlet(loadOnStartup = 1, value = "/")
public class ConnectorLimitServlet extends HttpServlet {

   @Override
   protected void doGet(HttpServletRequest req, HttpServletResponse
resp) throws IOException, ServletException {
     int number = Integer.parseInt(req.getParameter("number"));
     // Fake some work done at each stage of processing
     try { Thread.sleep(500); } catch (InterruptedException e) {}
     resp.setContentType("text/plain");
     if (number <= 1) {
       resp.getWriter().write("Finished " + req.getServletPath());
       return;
     }
     switch (req.getServletPath()) {
       case "/redirect":
         resp.sendRedirect(new URL(req.getScheme() + "://" +
req.getServerName() + ":" + req.getServerPort() +
             req.getRequestURI() + "?number=" + (number - 1)).toString());
         return;
       case "/forward":
         final String forwardAddress = "/forward?number=" + (number - 1);
         getServletContext().getRequestDispatcher(forwardAddress).forward(req,
resp);
     }
   }
}


It seems that under high load, 1000 threads in jmeter, Tomcat will
refuse some of the connections for nio2 connections but not for nio,
further it seems that these failures happen considerably earlier than
the configuration page would suggest would be the case. The
configuration suggests that if acceptCount is high enough for the
number of connections then they will be queued prior to reaching the
processing threads, so a small number of processing threads can exist
with a queue of connection feeding them, it seems like until
connectionTimeout is reached connections shouldn't be refused, but
that is not what occurs. In fact acceptCount seems to have very little
effect.
In short, my questions are:
Why is the nio2 connector type worse at this than nio type?
Why are connections refused before acceptCount is reached, or
connectionTimeout is reached?
I'm guessing that each forward or redirect effectively counts as an
extra connection, as removing the redirects and multipling the number
of jmeter threads suggests that is the case, am I correct here?

Also, I feel like it would help if there were better documentation
around the differences between nio2 and nio, as, for example, the
connector comparison part makes them sound almost the same.

Apologies if this has been covered elsewhere before, I have been
searching but haven't found anything particularly clear covering this.
Best regards, Peter

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org

Reply via email to