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. > > @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 > -- Guang <http://javadevnotes.com/java-long-to-string-examples/>