处理Spring MVC控制器中长时间运行的进程

时间:2017-02-19 23:54:50

标签: spring spring-mvc spring-boot

使用Spring MVC,我有一个控制器向外部服务发出API请求,这可能需要很长时间。我正在同步执行此操作,因为我想将外部请求结果返回给用户。理想情况下,这并不会在此期间阻塞整个线程,有点像async / await C#风格的习惯用法,但我不确定如何使用Spring(或其他东西)轻松地做到这一点。

3 个答案:

答案 0 :(得分:1)

您可以在某些服务方法上使用@Async注释进行异步执行。

答案 1 :(得分:0)

Spring MVC是建立在Servlet之上的,这意味着(默认情况下)你在Controller方法中做的任何事情都会阻塞Tomcat提供的请求线程(Tomcat是目前Spring Boot的默认servlet容器)。 如果要调用另一个基于HTTP的服务,或者在控制器内查询数据库,则可能正在进行阻塞IO调用。阻塞调用将始终阻塞调用线程,C#中的async / await只是语法糖,就像Springs @Async一样,它使用隐藏的ThreadPool来完成实际工作。

除非你能够使用NIO选择器调用上游服务,否则你需要一个线程来等待响应,在这种情况下,最好只阻塞Tomcat请求线程,我相信默认的数字请求线程数为150,但如果需要,可以将其设置得更高。如果可以以NIO方式调用上游服务,则只需要一个线程用于对该服务的所有调用,并且您可以从控制器返回DeferedResult,并在响应之后将响应写入客户端。上游服务已经生成。

答案 2 :(得分:0)

很简单。不要从主控制器方法调用长时间运行的api。只需返回视图(JSP)。然后,您可以在视图(Javascript)中从document.ready方法触发ajax请求。您可以在控制器中使用单独的@ResourceRequest带注释的方法来处理ajax调用。将api结果(作为JSON或其他内容)返回给ajax调用者。视图收到ajax响应后,根据需要更新UI。