On Thu, Sep 7, 2017 at 3:59 AM, Yasser Zamani <[email protected]>
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/>