On 9/7/2017 12:15 PM, Guang Chao wrote:
> On Thu, Sep 7, 2017 at 3:59 AM, Yasser Zamani <yasser.zam...@live.com>
> 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!
>>
>> 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!
>>
>> 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()));
>>      }
>>
>
> I'm not 100% sure, but it seems the doGet method code here is not correct.

Maybe you mean I should startAsync() inside Servlet's thread pool rather 
than tomcat's thread?

>
>
>>
>>      @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
>>
>
>
>

Reply via email to