Spring Boot REST - 请求未使用ThreadPoolTask​​Executor配置执行

时间:2017-09-11 18:12:01

标签: java spring-mvc spring-boot spring-restcontroller threadpoolexecutor

我正在尝试开发一个春季启动应用程序。我已经在没有spring框架的核心java中编写了所有核心实现。我在这个春季启动应用程序中使用该jar。我想管理我的休息控制器的并发性。因此,在主类中相应地配置了ThreadPoolTask​​Executor。理想情况下,我只想要2个并发请求进入execute()方法,我注释Async。我一次测试了2个并发请求,但我在日志中看到我的请求一次性进入execute()。所有任务都是内存密集型的。所以那些因堆内存问题而失败。我试图找出理想的并发数。我想知道我的配置是否正确或我遗失了什么?谢谢。

这是我的主要课程:

@SpringBootApplication
@EnableAsync
public class RestapiApplication implements AsyncConfigurer {

    public static void main(String[] args) {
        ApplicationContext ctx = SpringApplication.run(RestapiApplication.class, args);
        System.out.println("Rightdata Middleware ready to accept requests:");
    }

    @Bean(name = "executor1")
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        taskExecutor.setMaxPoolSize(2);
        taskExecutor.setCorePoolSize(2);
        taskExecutor.setThreadNamePrefix("LULExecutor-");
        taskExecutor.setQueueCapacity(100);
        taskExecutor.initialize();
        return taskExecutor;
    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return new SimpleAsyncUncaughtExceptionHandler();
    }
}

这是我的REST控制器:

@RestController
@RequestMapping("/end2end")
public class End2EndRestController {

    /**
     * The log.
     */
    private final Logger log = LoggerFactory.getLogger(this.getClass());

    @RequestMapping(method = RequestMethod.POST)
    public JSONObjectPOJO process(@RequestBody String end2EndScenarioString) throws InterruptedException, ExecutionException {

        final JSONObjectPOJO jsonObjectPOJO = convertToJavaObject(end2EndScenarioString);
        final ExecutorService executor = Executors.newSingleThreadExecutor();
        executor.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    execute(jsonObjectPOJO);
                } catch (Exception e) {
                    e.getMessage();
                }
            }});
            executor.shutdown();
            return jsonObjectPOJO;
        }

    @Async("executor1")
    private void execute(JSONObjectPOJO jsonObjectPOJO) throws Exception {
        ExecutorService executorService = Executors.newFixedThreadPool(2);
        Future<?> futureTarget;
        Future<?> futureSource;
        futureSource = processSource(executorService);
        futureTarget = processTarget(executorService);
        manageSourceProcessingResults(futureSource);
        manageTargetProcessingResults(futureTarget);
        executorService.shutdown();
        //Do rest of the tasks.
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    protected Future<?> processSource(executorService){
        //Get appropriate class instance with call() - coreActionClass.
        Future<?> futureSource = executorService.submit(coreActionClass);
        return futureSource;
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    protected Future<?> processTarget(executorService){
        //Get appropriate class instance with call() - coreActionClass.
        Future<?> futureTarget = executorService.submit(coreActionClass); //callable method in core.
        return futureTarget;
    }

    private void manageSourceProcessingResults(Future<?> futureSource) {
        try{
            futureSource.get();
        } catch(Exception e){
            e.printStackTrace();
        }
    }

    private void manageTargetProcessingResults(Future<?> futureTarget) {
        try{
            futureTarget.get();
        } catch(Exception e){
            e.printStackTrace();
        }
    }
}

更新-1:

我现在已将代码更改为以下内容:

@RestController
@RequestMapping("/end2end")
public class End2EndRestController {

    /**
     * The log.
     */
    private final Logger log = LoggerFactory.getLogger(this.getClass());

    @RequestMapping(method = RequestMethod.POST)
    public JSONObjectPOJO process(@RequestBody String end2EndScenarioString) throws InterruptedException, ExecutionException {

        final JSONObjectPOJO jsonObjectPOJO = convertToJavaObject(end2EndScenarioString);
        final ExecutorService executor = Executors.newSingleThreadExecutor();
        executor.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    execute(jsonObjectPOJO);
                } catch (Exception e) {
                    e.getMessage();
                }
            }});
            executor.shutdown();
            return jsonObjectPOJO;
        }    
}

和AsyncService类:

public class AsyncService {

    @Async("executor1")
    public void execute(JSONObjectPOJO jsonObjectPOJO) throws Exception {
        ExecutorService executorService = Executors.newFixedThreadPool(2);
        Future<?> futureTarget;
        Future<?> futureSource;
        futureSource = processSource(executorService);
        futureTarget = processTarget(executorService);
        manageSourceProcessingResults(futureSource);
        manageTargetProcessingResults(futureTarget);
        executorService.shutdown();
        //Do rest of the tasks.
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    protected Future<?> processSource(executorService){
        //Get appropriate class instance with call() - coreActionClass.
        Future<?> futureSource = executorService.submit(coreActionClass);
        return futureSource;
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    protected Future<?> processTarget(executorService){
        //Get appropriate class instance with call() - coreActionClass.
        Future<?> futureTarget = executorService.submit(coreActionClass); //callable method in core.
        return futureTarget;
    }

    private void manageSourceProcessingResults(Future<?> futureSource) {
        try{
            futureSource.get();
        } catch(Exception e){
            e.printStackTrace();
        }
    }

    private void manageTargetProcessingResults(Future<?> futureTarget) {
        try{
            futureTarget.get();
        } catch(Exception e){
            e.printStackTrace();
        }
    }
}
  1. 我的理解是当我不再配置maxpoolsize(2)时 两次请求一次只能在execute()方法中。为一个 新的请求进入,之前的请求之一必须完成 它的执行。我的理解是否正确? async会适用吗? 内部执行人服务?
  2. 我认为一次只处理2个请求 每个请求都可以产生2个不同的线程并完成 它的任务。请澄清。

1 个答案:

答案 0 :(得分:0)

我看到两个问题。

1)在process方法中,您正在创建一个新的ExecutorService。这不是必需的。而是在检索execute后调用jsonObjectPOJO方法。

2)你不能在它实现的同一个类中使用@Async int。您需要创建一个新类,让我们调用MyAsyncService来包含@Async方法。这是因为面向方面的编程正在进行中。

查看this link了解详情。以下是该链接的引用。

  

首先 - 让我们回顾一下规则 - @Async有两个限制:

     

它必须仅适用于公共方法   自调用 - 从同一个类中调用异步方法 - 将无法正常工作   原因很简单 - 该方法需要公开才能被代理。并且自调用不起作用,因为它绕过代理并直接调用底层方法。

编辑1:

@RestController
@RequestMapping("/end2end")
public class End2EndRestController {

@AutoWired
AsyncService asyncService;

private final Logger log = LoggerFactory.getLogger(this.getClass());
@RequestMapping(method = RequestMethod.POST)
public JSONObjectPOJO process(@RequestBody String end2EndScenarioString) throws InterruptedException, ExecutionException {
    final JSONObjectPOJO jsonObjectPOJO = convertToJavaObject(end2EndScenarioString);
    asyncService.execute(jsonObjectPOJO);
    return jsonObjectPOJO;
}




public class AsyncService {

    @Async("executor1")
    public void execute(JSONObjectPOJO jsonObjectPOJO) throws Exception {
        //No Futures, no ExecutorServices, just process that request.
    }

}

通过创建和配置ThreadPoolTask​​Executor只使用2个线程,您已经实现了目标。

EDIT2:Spring @Async limit number of threads