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