6

When invoking a Callable method via ajax running on a Spring Boot application, the embedded tomcat is handling requests asynchronously and perfectly fine:

2017-07-02 09:12:24.283  INFO 3582 --- [nio-8090-exec-3] c.r.web.controllers.MainController       : Ali was stored in redis
2017-07-02 09:12:25.671  INFO 3582 --- [ngAsyncThread-1] c.r.web.controllers.MainController       : Ali is searching for a chat
2017-07-02 09:12:25.820  INFO 3582 --- [ngAsyncThread-1] c.r.web.controllers.MainController       : Ali last activity date was updated in redis
2017-07-02 09:12:26.053  INFO 3582 --- [ngAsyncThread-1] c.r.web.controllers.MainController       : Ali retrieving random conv null
2017-07-02 09:12:26.054  INFO 3582 --- [ngAsyncThread-1] c.r.web.controllers.MainController       : Ali created my own conversation
2017-07-02 09:12:26.211  INFO 3582 --- [ngAsyncThread-1] c.r.web.controllers.MainController       : Ali searching...
2017-07-02 09:12:27.927  INFO 3582 --- [ngAsyncThread-1] c.r.web.controllers.MainController       : Ali searching...
2017-07-02 09:12:29.128  INFO 3582 --- [ngAsyncThread-1] c.r.web.controllers.MainController       : Ali searching...
2017-07-02 09:12:29.305  INFO 3582 --- [nio-8090-exec-2] c.r.web.controllers.MainController       : Zeina was stored in redis
2017-07-02 09:12:29.984  INFO 3582 --- [ngAsyncThread-2] c.r.web.controllers.MainController       : Zeina is searching for a chat
2017-07-02 09:12:30.135  INFO 3582 --- [ngAsyncThread-2] c.r.web.controllers.MainController       : Zeina last activity date was updated in redis
2017-07-02 09:12:30.285  INFO 3582 --- [ngAsyncThread-2] c.r.web.controllers.MainController       : Zeina retrieving random conv Conversation [id=bbb17857-9049-4, person1=Person [id=9a243d57-2f0c-4, name=Ali, age=22, gender=M, ip=0:0:0:0:0:0:0:1, loginDate=Sun Jul 02 09:12:23 EEST 2017, lastActiveDate=Sun Jul 02 09:12:25 EEST 2017], person2=null, creationDate=Sun Jul 02 09:12:26 EEST 2017]
2017-07-02 09:12:30.687  INFO 3582 --- [ngAsyncThread-1] c.r.web.controllers.MainController       : Ali searching...
2017-07-02 09:39:54.420  INFO 3582 --- [ngAsyncThread-3] c.r.web.controllers.MainController       : Zeina is searching for a chat

However, when I deploy the application on an external tomcat server, one call is hanging the server and the next one is only processed after the completion of the first call.

2017-07-02 06:47:57.285  INFO 3324 --- [SpringAsyncThread-4] c.r.web.controllers.MainController       : Zanzoun searching...
2017-07-02 06:47:58.297  INFO 3324 --- [SpringAsyncThread-4] c.r.web.controllers.MainController       : Zanzoun searching...
2017-07-02 06:47:59.309  INFO 3324 --- [SpringAsyncThread-4] c.r.web.controllers.MainController       : Zanzoun searching...
2017-07-02 06:48:00.323  INFO 3324 --- [SpringAsyncThread-4] c.r.web.controllers.MainController       : Zanzoun searching...
2017-07-02 06:48:01.335  INFO 3324 --- [SpringAsyncThread-4] c.r.web.controllers.MainController       : Zanzoun searching...
2017-07-02 06:48:02.347  INFO 3324 --- [SpringAsyncThread-4] c.r.web.controllers.MainController       : Zanzoun searching...
2017-07-02 06:48:03.359  INFO 3324 --- [SpringAsyncThread-4] c.r.web.controllers.MainController       : Zanzoun searching...
2017-07-02 06:48:04.388  INFO 3324 --- [SpringAsyncThread-4] c.r.web.controllers.MainController       : Zanzoun remove dead conversatio
2017-07-02 06:48:04.682  INFO 3324 --- [SpringAsyncThread-5] c.r.web.controllers.MainController       : AJ is searching for a chat
2017-07-02 06:48:04.695  INFO 3324 --- [SpringAsyncThread-5] c.r.web.controllers.MainController       : AJ last activity date was updated in redis
2017-07-02 06:48:04.708  INFO 3324 --- [SpringAsyncThread-5] c.r.web.controllers.MainController       : AJ retrieving random conv Conversation [id=f5fe39ac-91ce-4, person1=Person [id=e25d18f3-9729-4, name=Zanzoun, age=12, gender=F, ip=91.197.46.40, loginDate=Sun Jul 02 06:47:32 UTC 2017, lastActiveDate=Sun Jul 02 06:47:48 UTC 2017], person2=null, creationDate=Sun Jul 02 06:47:48 UTC 2017]
2017-07-02 06:48:50.833  INFO 3324 --- [SpringAsyncThread-6] c.r.web.controllers.MainController       : AJ is searching for a chat
2017-07-02 06:48:50.845  INFO 3324 --- [SpringAsyncThread-6] c.r.web.controllers.MainController       : AJ last activity date was updated in redis
2017-07-02 06:48:50.860  INFO 3324 --- [SpringAsyncThread-6] c.r.web.controllers.MainController       : AJ retrieving random conv null
2017-07-02 06:48:50.860  INFO 3324 --- [SpringAsyncThread-6] c.r.web.controllers.MainController       : AJ created my own conversation
2017-07-02 06:48:50.872  INFO 3324 --- [SpringAsyncThread-6] c.r.web.controllers.MainController       : AJ searching...
2017-07-02 06:48:51.884  INFO 3324 --- [SpringAsyncThread-6] c.r.web.controllers.MainController       : AJ searching...
2017-07-02 06:48:52.896  INFO 3324 --- [SpringAsyncThread-6] c.r.web.controllers.MainController       : AJ searching...
2017-07-02 06:48:53.908  INFO 3324 --- [SpringAsyncThread-6] c.r.web.controllers.MainController       : AJ searching...
2017-07-02 06:48:54.921  INFO 3324 --- [SpringAsyncThread-6] c.r.web.controllers.MainController       : AJ searching...

In the above log, the call from Zanzoun and AJ were sent at the same time, however AJ processing didn't start until Zanzoun was over.

Below I list my configurations:

@Configuration
@EnableAsync
public class MvcConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/").setViewName("main");
        registry.addViewController("/login").setViewName("login");
        registry.addViewController("/admin").setViewName("admin");
    }

    @Override
    public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
        configurer.setTaskExecutor(asyncTaskExecutor());
    }

    @Bean
    public AsyncTaskExecutor asyncTaskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(10);
        executor.setMaxPoolSize(200);
        executor.setQueueCapacity(500);
        executor.setThreadNamePrefix("SpringAsyncThread-");
        executor.initialize();
        return executor;
    }
}

@SpringBootApplication
@EnableScheduling
@EnableAsync
public class App extends SpringBootServletInitializer {
    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(App.class);
    }
}

Update 1

I applied the answer provided in the comments by @divine , however the problem was not solved:

<Connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol" 
               minProcessors="3"
               maxProcessors="8"
               maxThreads="20"
               connectionTimeout="150000" 
               asyncTimeout="150000" />

Update 2

I have tested locally on my Linux machine using an external Tomcat 8.0.21 and it works perfectly. However, I installed also the same version of Tomcat in Windows (It's actually an AWS instance), and the problem remains the same, so it's an OS/Version issue?

Update 3

Here's the pom file as requested:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.randomni</groupId>
    <artifactId>web</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>

    <!-- Define that this project is a child of the spring-boot-starter-parent 
        project which contains all default maven configuration, this project inherits 
        all these configurations -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.3.RELEASE</version>
    </parent>

    <dependencies>
        <!-- Main Web Dependency, contains MVC and Tomcat -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-mobile</artifactId>
        </dependency>
        <!-- Spring MVC with Thymeleaf views -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <!-- Security -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <!-- WebJars -->
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>webjars-locator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>sockjs-client</artifactId>
            <version>1.0.2</version>
        </dependency>
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>stomp-websocket</artifactId>
            <version>2.3.3</version>
        </dependency>
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>jquery</artifactId>
            <version>3.1.0</version>
        </dependency>
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>normalize.css</artifactId>
            <version>5.0.0</version>
        </dependency>
        <!-- For Deployment -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>
        </dependency>
    </dependencies>

    <properties>
        <java.version>1.8</java.version>
        <!-- Default Thymeleaf of Spring Boot is version 2, so we had to add these -->
        <thymeleaf.version>3.0.6.RELEASE</thymeleaf.version>
        <thymeleaf-layout-dialect.version>2.2.2</thymeleaf-layout-dialect.version>
    </properties>

</project>
8
  • 1
    take a look at this answer. stackoverflow.com/a/8446513/4525120 Commented Jul 7, 2017 at 7:42
  • @divine please check Update #1. Commented Jul 7, 2017 at 20:05
  • 'When running with embedded tomcat it works fine but when deployed in external tomcat output is not same'- this is the second thread iam noticing this type of issue. Probably because of the tomcat server config not allowing async requests Commented Jul 7, 2017 at 20:10
  • Try debugging o.s.a.i.AsyncExecutionAspectSupport.determineAsyncExecutor() method to get the idea of what executor you are getting exactly in either case. Commented Jul 7, 2017 at 21:05
  • @jihor the determineAsyncExecutor() was never invoked because the interceptor was not of type InterceptorAndDynamicMethodMatcher. However I found new things, please check Update #2. Commented Jul 8, 2017 at 4:40

1 Answer 1

-1

Have you tried checking the real pool size, for example, through JMX: https://wiki.apache.org/tomcat/FAQ/Monitoring#Thread_Usage?

Also, could you try installing APR Native library to verify the problem is not with auto-selected protocol for incoming traffic: https://tomcat.apache.org/tomcat-8.0-doc/apr.html

The configuration of Windows EC2 instance may also influence the observed behaviour, could you add it to the question, too?

Sign up to request clarification or add additional context in comments.

5 Comments

on the face, i don't really like this answer. Suggestions for possible research opportunities and requests for more information should be a comment instead of an answer.
@Jason neither did I like it as an answer: my reputation yet doesn't allow to leave a comment to the post, was there a different way to communicate with OP?
unfortunately other than direct messaging no. However, leaving such answers is considered abuse of the answering system as answers need to be kept to concise explanations of the problem. If commenting must wait until you have the requisite 50 rep, so be it.
Well, at least I tried to participate, if that is considered abusive, that doesn't inspire to help people any further, it's just a pity to hear something like that. I tried to cover the directions to investigate for the OP, as obviously there hasn't been any answer besides that.
I get what you're saying about trying to participate, and my personal feeling toward the requisite 50 rep for commenting is there shouldn't be a requisite to comment. That being said, rules are rules, and answers are only for clear and concise explanations.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.