StreamingResponseBodyReturnValueHandler 不使用 applicationTaskExecutor
StreamingResponseBodyReturnValueHandler does not use applicationTaskExecutor
我有 Spring Data REST
个自定义控制器 returns ResponseEntity<StreamingResponseBody>
在我的 application.yaml 文件中,我定义了一个用于 StreamingResponseBody 的自定义任务执行器。
spring:
task:
execution:
pool:
max-size: 16
queue-capacity: 100
但是,mvc 仍然使用 SimpleAsyncTaskExecutor
,而不是上面定义的
An Executor is required to handle java.util.concurrent.Callable return values.
Please, configure a TaskExecutor in the MVC config under "async support".
The SimpleAsyncTaskExecutor currently in use is not suitable under load.
经过一些调试,我发现 StreamingResponseBodyReturnValueHandler
没有在 WebAsyncTask
类型上设置 applicationTaskExecutor
,即 StreamingResponseBodyTask
,结果 [=使用 16=]。
Callable<Void> callable = new StreamingResponseBodyTask(outputMessage.getBody(), streamingBody);
WebAsyncUtils.getAsyncManager(webRequest).startCallableProcessing(callable, mavContainer);
当我在 WebMvcAutoConfiguration
中调试此方法时,WebMvcAutoConfiguration
正在获取 applicationTaskExecutor
并正确设置它
@Override
public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
if (this.beanFactory.containsBean(TaskExecutionAutoConfiguration.APPLICATION_TASK_EXECUTOR_BEAN_NAME)) {
Object taskExecutor = this.beanFactory
.getBean(TaskExecutionAutoConfiguration.APPLICATION_TASK_EXECUTOR_BEAN_NAME);
if (taskExecutor instanceof AsyncTaskExecutor) {
configurer.setTaskExecutor(((AsyncTaskExecutor) taskExecutor));
}
}
Duration timeout = this.mvcProperties.getAsync().getRequestTimeout();
if (timeout != null) {
configurer.setDefaultTimeout(timeout.toMillis());
}
}
我错过了什么吗?如何将 ThreadPoolTaskExecutor
应用于 StreamingResponseBody
?
spring-data-rest
自定义存储库(@RepositoryRestResource
或 @BasePathAwareController
)忽略 AsyncSupportConfigurer
见 RepositoryRestMvcConfiguration#repositoryExporterHandlerAdapter
here.
但是 spring-webmvc
适用 AsyncSupportConfigurer
请参见 WebMvcConfigurationSupport#requestMappingHandlerAdapter
here
AsyncSupportConfigurer configurer = getAsyncSupportConfigurer();
if (configurer.getTaskExecutor() != null) {
adapter.setTaskExecutor(configurer.getTaskExecutor());
}
if (configurer.getTimeout() != null) {
adapter.setAsyncRequestTimeout(configurer.getTimeout());
}
adapter.setCallableInterceptors(configurer.getCallableInterceptors());
adapter.setDeferredResultInterceptors(configurer.getDeferredResultInterceptors());
如果可能,请使用简单的 @RestController
或 @Controller
,
如果没有,您可以创建一个问题 here 来添加对此的支持
我有 Spring Data REST
个自定义控制器 returns ResponseEntity<StreamingResponseBody>
在我的 application.yaml 文件中,我定义了一个用于 StreamingResponseBody 的自定义任务执行器。
spring:
task:
execution:
pool:
max-size: 16
queue-capacity: 100
但是,mvc 仍然使用 SimpleAsyncTaskExecutor
,而不是上面定义的
An Executor is required to handle java.util.concurrent.Callable return values.
Please, configure a TaskExecutor in the MVC config under "async support".
The SimpleAsyncTaskExecutor currently in use is not suitable under load.
经过一些调试,我发现 StreamingResponseBodyReturnValueHandler
没有在 WebAsyncTask
类型上设置 applicationTaskExecutor
,即 StreamingResponseBodyTask
,结果 [=使用 16=]。
Callable<Void> callable = new StreamingResponseBodyTask(outputMessage.getBody(), streamingBody);
WebAsyncUtils.getAsyncManager(webRequest).startCallableProcessing(callable, mavContainer);
当我在 WebMvcAutoConfiguration
WebMvcAutoConfiguration
正在获取 applicationTaskExecutor
并正确设置它
@Override
public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
if (this.beanFactory.containsBean(TaskExecutionAutoConfiguration.APPLICATION_TASK_EXECUTOR_BEAN_NAME)) {
Object taskExecutor = this.beanFactory
.getBean(TaskExecutionAutoConfiguration.APPLICATION_TASK_EXECUTOR_BEAN_NAME);
if (taskExecutor instanceof AsyncTaskExecutor) {
configurer.setTaskExecutor(((AsyncTaskExecutor) taskExecutor));
}
}
Duration timeout = this.mvcProperties.getAsync().getRequestTimeout();
if (timeout != null) {
configurer.setDefaultTimeout(timeout.toMillis());
}
}
我错过了什么吗?如何将 ThreadPoolTaskExecutor
应用于 StreamingResponseBody
?
spring-data-rest
自定义存储库(@RepositoryRestResource
或 @BasePathAwareController
)忽略 AsyncSupportConfigurer
见 RepositoryRestMvcConfiguration#repositoryExporterHandlerAdapter
here.
但是 spring-webmvc
适用 AsyncSupportConfigurer
请参见 WebMvcConfigurationSupport#requestMappingHandlerAdapter
here
AsyncSupportConfigurer configurer = getAsyncSupportConfigurer();
if (configurer.getTaskExecutor() != null) {
adapter.setTaskExecutor(configurer.getTaskExecutor());
}
if (configurer.getTimeout() != null) {
adapter.setAsyncRequestTimeout(configurer.getTimeout());
}
adapter.setCallableInterceptors(configurer.getCallableInterceptors());
adapter.setDeferredResultInterceptors(configurer.getDeferredResultInterceptors());
如果可能,请使用简单的 @RestController
或 @Controller
,
如果没有,您可以创建一个问题 here 来添加对此的支持