On 07/09/17 22:22, Yasser Zamani wrote: > 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
You are unlikely to get much interest on this list until you upgrade to the latest stable 7.0.x (or 8.0.x). So much has changed in the ~4 years since 7.0.47 that there isn't much value in investigating this. If you see the same or similar issues with 7.0.81, that would be more interesting. Mark > >> >> 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 >> > > --------------------------------------------------------------------- > 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