At first thanks a lot for your reply!

On 9/7/2017 1:43 PM, Mark Thomas wrote:
> On 06/09/17 20:59, Yasser Zamani wrote:
>> Hi there,
>>
>> I'm studying Servlet 3's async API using tomcat. I see following strange
>> behavior from tomcat in a very simple test app!
>
> You are also using the BIO connector which, since it is blocking,
> doesn't offer any benefits when using async. You'd be better off with
> the NIO connector.

Yes I know but currently it's not important for me. I am studying 
Servlet 3's async API and BIO keeps it simpler to study and focus only 
on it (with NIO I cannot know if something is because of Servlet 3's 
async API or Tomcat's NIO).

>
> You haven't told us which Tomcat version you are using. Since you are
> using BIO that narrows it down a bit to 7.0.x or 8.0.x but that is still
> a lot of possibilities.

It's 7.0.47

>
> Neither have you told us what operating system you are using. My
> experience of JMeter under load, particularly on Windows, is that you
> see strange behaviour and it can be hard to figure out the interaction
> of JMeter, the OS network stack and Tomcat.
>
> You also haven't told us what hardware this test is running on.
> Particularly the number of cores available.
>

OS Name Microsoft Windows 8.1 Enterprise
System Type     x64-based PC
Processor       Intel(R) Core(TM) i3-4130 CPU @ 3.40GHz, 3400 Mhz, 2 Core(s), 
4 Logical Processor(s)


>> I have following JMeter test plan:
>> Number of threads (users): 700
>> Ramp-Up period (in seconds): 23
>> Loop count: 1
>>
>> So JMeter generates 30.43 requests per second and 304.3 requests per 10
>> seconds. I'm planning to full tomcat's BIO pool and accept buffer :)
>>
>> I have an always async test servlet which on destroy, I print tomcat
>> container max used threads count. It prints 187 for me which is lower
>> than 200 (tomcat default pool size) so I should not get any "connection
>> refuse" but I get!
>
> There are all sorts of possible reasons for that. I'd suggest scaling
> down the test. Limit Tomcat to 20 threads. Reduce the load similarly.
> Increase the sleep time. You want to ensure that the only limit you are
> hitting is the one you are trying to hit.
>

Previously I also tested very low loads but again as you suggested I 
tested following low load configuration and get even worse results!! 
Tomcat successfully returns from request below 29th but fails 25 
requests of 29th to 70th. However this time all fails are "connection 
refuse" and there are not any "connection reset". Whilst the program 
output is "Container MAX used threads: 10" !!

CONFIGURATION #2:

Server.xml
<Connector port="7780" protocol="org.apache.coyote.http11.Http11Protocol"
                connectionTimeout="120000"
           maxThreads="20" maxConnections="20" acceptCount="10"
                redirectPort="7743" />

JMeter
Number of threads (users): 70
Ramp-Up period (in seconds): 35 (40 requests per 20 seconds)
Loop count: 1

My async servlet
Async Sleep Time: 20 seconds (ensures 40 concurrent requests)
It's own thread pool size: 41 (lower than 40 so never fulls)

JMETER RESULT of RESPONSE TIMES #2:
Max: 38 seconds (lower then tomcat and asyncContext timeout)
MIN: 20 seconds
AVG: 18 seconds (because of fails)
ERR: 36%

UTPUT:

Container MAX used threads: 10

Thanks in advance!

> Mark
>
>
>> I have simulated a blocking operation by a sleep for 10 seconds. When my
>> servlet gets a request, it quickly starts an async and add further
>> processing to my own thread pool (container thread comes back to pool
>> quickly, right). My own thread pool size is 310 which is greater than
>> 304.3 (requests in 10 seconds) so never full.
>>
>> I've tested several times. Tomcat successfully returns from all requests
>> below 326th but fails 102 requests from 326th to 700th with "connection
>> refuse" and afew with "connection reset".
>>
>> Why?! My own thread pool does the jobs and Tomcat's pool is free (my
>> servlet uses 187 threads of tomcat at max).
>>
>> Thanks in advance!
>>
>> JMETER RESULT of RESPONSE TIMES:
>> Max: 60 seconds (lower then tomcat and asyncContext timeout)
>> MIN: 10 seconds
>> AVG: 37 seconds
>> ERR: 15%
>>
>> CONFIGURATIONS:
>>
>> Server.xml
>> <Connector port="7780" protocol="org.apache.coyote.http11.Http11Protocol"
>>                 connectionTimeout="120000"
>>                 redirectPort="7743" />
>>
>> Async.java
>>
>> package com.sstr.example;
>>
>> import javax.servlet.*;
>> import javax.servlet.annotation.WebInitParam;
>> import javax.servlet.annotation.WebServlet;
>> import javax.servlet.http.HttpServlet;
>> import javax.servlet.http.HttpServletRequest;
>> import javax.servlet.http.HttpServletResponse;
>> import java.io.IOException;
>> import java.util.concurrent.ExecutorService;
>> import java.util.concurrent.Executors;
>> import java.util.concurrent.ThreadFactory;
>>
>> @WebServlet(
>>          name = "async",
>>          value = {"/async"},
>>          asyncSupported = true,
>>          initParams = {
>>                  @WebInitParam(name = "JobPoolSize", value = "310")
>>          }
>> )
>> public class Async extends HttpServlet {
>>
>>      public final int REQUEST_TIMEOUT = 120000;
>>      private ExecutorService exe;
>>
>>      @Override
>>      public void init() throws ServletException {
>>          int size = Integer.parseInt(getInitParameter("JobPoolSize"));
>>          exe = Executors.newFixedThreadPool(
>>                  size,
>>                  new ThreadFactory() {
>>                      @Override
>>                      public Thread newThread(Runnable r) {
>>                          return new Thread(r, "Async Processor");
>>                      }
>>                  }
>>          );
>>      }
>>
>>      @Override
>>      protected void doGet(HttpServletRequest req, HttpServletResponse
>> resp) throws ServletException, IOException {
>>          final AsyncContext context = req.startAsync();
>>          context.setTimeout(REQUEST_TIMEOUT);
>>          exe.execute(new ContextExecution(context,
>> Thread.currentThread().getName()));
>>      }
>>
>>      @Override
>>      public void destroy() {
>>          System.out.println("Container MAX used threads: " + threadCount);
>>          exe.shutdown();
>>      }
>>
>>      int threadCount = 0;
>>      class ContextExecution implements Runnable {
>>
>>          final AsyncContext context;
>>          final String containerThreadName;
>>
>>          public ContextExecution(AsyncContext context, String
>> containerThreadName) {
>>              this.context = context;
>>              this.containerThreadName = containerThreadName;
>>          }
>>
>>          @Override
>>          public void run() {
>>              try {
>>                  int threadNumber =
>> Integer.parseInt(containerThreadName.substring(
>>                          containerThreadName.lastIndexOf('-')+1));
>>                  if(threadNumber > threadCount) {
>>                      threadCount = threadNumber;
>>                  }
>>
>>                  // Simulate Time Consuming Task
>>                  Thread.sleep(10000);
>>
>>                  ServletResponse resp = context.getResponse();
>>                  if (resp != null) {
>>                      resp.getWriter().write("Ok");
>>                  }
>>
>>                  context.complete();
>>              } catch (Exception e) {
>>                  // Handle ?
>>              }
>>          }
>>      }
>> }
>>
>> OUTPUT:
>>
>> Container MAX used threads: 187
>>
>> ---------------------------------------------------------------------
>> 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