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: [email protected]
>>> For additional commands, e-mail: [email protected]
>>>
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: [email protected]
>> For additional commands, e-mail: [email protected]
>>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [email protected]
> For additional commands, e-mail: [email protected]
>
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]