Spring Boot中的异步控制器

时间:2019-05-09 11:01:09

标签: rest spring-boot asynchronous

我已经使用Spring Boot创建了Web服务,并且其中有一个rest控制器,该控制器通过基于供应商的JDBC驱动程序访问数据库并获取记录。在此过程中,检索到的记录数超过80K条记录。因此,无论何时我们以客户端身份访问其余端点,我们都会遇到超时错误。

我尝试使用下面的教程设置异步调用。但是不幸的是,其余调用仍在超时。

https://howtodoinjava.com/spring-boot2/enableasync-async-controller/

控制器

    @RequestMapping(value = "/v1/lr/fullpositionasync", produces = {APPLICATION_JSON_UTF8_VALUE},   method = RequestMethod.GET)
    @ResponseBody
    public CompletableFuture<List<Position>> retrieveTradePositionsFullAsync(HttpServletRequest request, HttpServletResponse response) throws ExecutionException, InterruptedException {

        CompletableFuture<List<Position>> positionList =null;
        try {
            positionList = positionService.getFullPosition();
        }
        catch(Exception e){
            log.info("Error Occurred in Controller is:"+e.getMessage());
        }
        CompletableFuture.allOf(positionList).join();
        log.info(String.valueOf(positionList.get()));
        return positionList;
    }

服务

@Service
@Slf4j
public class PositionServiceImpl implements PositionService {

    @Autowired
    private PositionDao positionDao;

    @Async("asyncExecutor")
    @Override
    public CompletableFuture<List<Position>> getFullPosition()  {

        List<Position> fullpositionList = null;
        log.info("Getting the full Position process started");
        fullpositionList = positionDao.retrieveData();
        log.info("Total Positions retrieved:"+fullpositionList.size());
        try {
            log.info("Thread is about to sleep 1000 milliseconds");
            Thread.sleep(1000);
        }catch(InterruptedException e){
            log.info(e.getMessage());
        }
        log.info("Full Positions retrieval completed");
        return CompletableFuture.completedFuture(fullpositionList);
    }


}

配置

@Configuration
@EnableAsync
@Slf4j
public class AsyncConfiguration
{
    @Bean(name = "asyncExecutor")
    public Executor asyncExecutor()
    {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(20);
        executor.setMaxPoolSize(1000);
        executor.setWaitForTasksToCompleteOnShutdown(true);
        executor.setThreadNamePrefix("AsynchThreadForEndPoint-");
        executor.initialize();
        log.info("Executor is :"+executor.toString());
        return executor;
    }
}

DAO

@Repository
public class PositionDaoImpl implements PositionDao {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    private static final String ALL_POSITION_QUERY = "call AllPositionProcedure()";


    public List<Position> retrieveData() {
        return jdbcTemplate.query(ALL_POSITION_QUERY, new BeanPropertyRowMapper(Position.class));
        //  List<Map<String, Object>> mapList = jdbcTemplate.queryForList(sql);

    }

2 个答案:

答案 0 :(得分:0)

您不能使用JDBC在数据库上执行异步操作。 JDBC正在阻塞,因此它将阻塞您的线程,直到执行操作为止。如果要以异步方式执行操作,请使用R2DBC而不是JDBC。

答案 1 :(得分:0)

对于您的用例,最好的方法是将您的应用程序转换为反应式流(Flux)。

Flux是Reactive Streams发布者。它是JVM的完全无阻塞的反应式编程基础,具有高效的需求管理(以管理“背压”的形式)。它直接与Java 8功能API集成在一起,尤其是CompletableFuture,Stream和Duration。它提供可组合的异步序列API Flux(用于[N]个元素)和Mono(用于[0 | 1]个元素),从而广泛实现了Reactive Streams规范。

在现有应用中实施非常简单。只需更改您的存储库返回类型Flux而不是List或Future。

有关更多信息,您可以参考Here