带有StreamingResponseBody async.request-timeout的@RestController不起作用

时间:2018-10-23 11:22:10

标签: rest spring-boot asynchronous

我正在尝试通过长时间运行的工作从@RestController获取StreamingResponseBody。无论我尝试哪种配置,它都会在30秒后超时。

这是在Spring Boot 2.0.3中。 我使用了下面的测试,该测试显示了相同的行为来尝试正确配置。

@RestController
public class TestController {

    @RequestMapping("/streamtest")
    public StreamingResponseBody handleRequest () {
        return new StreamingResponseBody() {
            @Override
            public void writeTo (OutputStream out) throws IOException {
                for (int i = 0; i < 100000; i++) {
                    out.write((Integer.toString(i) + " - ").getBytes());
                    out.flush();
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
       };
   }
}

我尝试了此处定义的async.request-timeout设置; Async timeout downloading a large file using StreamingResponseBody on Spring Boot

我尝试覆盖WebMvcConfig设置超时。永远不会调用此方法。

@EnableWebMvc
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    @Override
    public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
        configurer.setDefaultTimeout(3600000);
        WebMvcConfigurer.super.configureAsyncSupport(configurer);
    }
}

我尝试定义ThreadPoolTask​​Executor:

@Configuration
@EnableAsync
@EnableScheduling
public class AsyncConfig implements AsyncConfigurer {

    @Override
    public Executor getAsyncExecutor() {
        return new ThreadPoolTaskExecutor();
    }
}

它总是在30秒后超时并显示日志;

12:14:28.028 [http-nio-8080-exec-2] DEBUG c.b.b.bof_static.config.BofStaticExceptionHandler - Async timeout for GET [/streamtest]
12:14:28.028 [http-nio-8080-exec-2] DEBUG org.springframework.web.servlet.DispatcherServlet - Null ModelAndView returned to DispatcherServlet with name 'dispatcherServlet': assuming HandlerAdapter completed request handling
12:14:28.028 [http-nio-8080-exec-2] DEBUG org.springframework.web.servlet.DispatcherServlet - Successfully completed request
12:14:28.030 [http-nio-8080-exec-2] DEBUG o.s.security.web.access.ExceptionTranslationFilter - Chain processed normally

我找不到其他解决方案。谁能指出缺少的东西吗?

3 个答案:

答案 0 :(得分:0)

我已经在计算机上设置了一个Spring Boot项目,其配置类如下所示,

@Configuration
@EnableWebMvc
@EnableTransactionManagement
public class MyConfiguration extends WebMvcConfigurerAdapter {
  ...
  ...
}

我只是将@EnableAsync添加到它的下面,并在覆盖方法

    @Configuration
    @EnableWebMvc
    @EnableTransactionManagement
    @EnableAsync
    public class MyConfiguration extends WebMvcConfigurerAdapter {
      ...
      ...
    @Override
    public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
      configurer.setDefaultTimeout(3600000);
    }
   }

我只是将您的方法带到了我的一个控制器类,然后大摇大摆地击中了它。我几分钟都没看到问题。 当我在没有对配置进行以上更改的情况下放置您的方法时,我会得到

2018-10-24 11:35:55.085 ERROR 78852 --- [nio-8080-exec-6] c.h.a.a.aop.MyExceptionHandler       : Async timeout for GET [/test/common/streamtest]

所以对我来说一切似乎都很好。

我对您代码的唯一猜测是,您可能将@EnableAsync放在了错误的位置。

此外,请尽量减少操作,现在不要尝试使用ThreadPoolTaskExecutor(),并使用默认值SimpleAsyncTaskExecutor执行请求。一旦让异步处理自定义超时,您就可以在以后插入它。

我正在嵌入式Tomcat中运行应用程序。

答案 1 :(得分:0)

在application.properties中设置以下选项可以解决此问题:

spring.mvc.async.request-timeout=-1

但是,如果您在代码中的任何地方实现WebMvcConfigurer,则上述选项将被忽略,因此必须将其设置为以下内容:

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
    // other config...
    @Override
    public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
        configurer.setDefaultTimeout(-1);
    }
}

您也可以将其设置为正整数(毫秒)。值-1将完全消除超时。

答案 2 :(得分:0)

打开application.properties添加以下行

# in milliseconds 
spring.mvc.async.request-timeout=5000 

如果这是生产代码,请不要将其值设置为-1。在大量请求的情况下,这可能导致资源匮乏。因为客户端永远不会超时,并且会保留他们正在使用的资源(线程)。