ero*_*ppa 9 spring spring-mvc spring-boot
我在 Spring Boot/Spring Data Rest 中有一个控制器,我的处理程序在其中下载这样的文件
@RequestMapping(method = GET, value = "/orderAttachments/{id}/download")
@ResponseStatus(HttpStatus.OK)
public ResponseEntity<StreamingResponseBody> downloadAttachment(@PathVariable("id") Long attachmentID, HttpServletRequest request)
throws IOException {
InputStream inputStream = fileManager.getInputStream(orderAttachment);
StreamingResponseBody responseBody = outputStream -> {
int numberOfBytesToWrite;
byte[] data = new byte[1024];
while ((numberOfBytesToWrite = inputStream.read(data, 0, data.length)) != -1) {
outputStream.write(data, 0, numberOfBytesToWrite);
}
inputStream.close();
};
return ResponseEntity
.ok()
.contentLength(orderAttachment.getFileSize())
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + orderAttachment.getFileName()+ "\"")
.contentType(MediaType.APPLICATION_OCTET_STREAM)
.body(responseBody);
}
Run Code Online (Sandbox Code Playgroud)
我在控制台中收到此错误
!!!
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.
-------------------------------
Request URI: '/api/v1/orderAttachments/163/download'
!!!
Run Code Online (Sandbox Code Playgroud)
但一切正常,我可以通过调用 API 下载文件
对于初学者来说,这是一个警告而不是错误。如果这是一个错误,您的应用程序将无法启动或工作。这是一个警告,告诉您SimpleAsyncTaskExecutor不应在生产中使用所使用的默认值。
将SimpleAsyncTaskExecutor创建一个新的Thread时候有什么需要被异步处理。每个线程默认占用 1MB 内存(和一些处理能力)。现在想象有人向这个 API 发出 100000 次调用。这也意味着 100000 个线程(乘以内存和每个 CPU 功率)。它会削弱您的应用程序,甚至可能会杀死它。
注意:如果您使用的是 Spring Boot 2.1.x 或更高版本,TaskExecutor则会为您配置和使用默认值。但是,如果您的配置中有禁用自动配置的内容(例如@EnableWebMvc在@Configuration类上)。要配置该执行程序(使用线程等),请查看Spring Boot 参考指南。
您还可以手动创建一个TaskExecutor并将其与 Spring MVC 相关联。
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Bean
public ThreadPoolTaskExecutor mvcTaskExecutor() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.setCorePoolSize(10);
taskExecutor.setMaxPoolSize(10);
return taskExecutor;
}
public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
configurer.setTaskExecutor(mvcTaskExecutor());
}
}
Run Code Online (Sandbox Code Playgroud)
现在这个专用的TaskExecutor将用于 Spring MVC 中的异步处理。但是,如前所述,如果您没有禁用自动配置(甚至可能是偶然的!),Spring Boot 应该已经预先配置了它。
这只是一个警告(这就是为什么您仍然能够下载请求的文件),Spring 建议定义您自己的文件,TaskExecutor而不是使用该SimpleAsyncTaskExecutor文件,正如消息所述,在负载下不适合。
SimpleAsyncTaskExecutor为每个任务启动一个新线程并且不重用它们。如果您没有配置并发线程限制,则默认为无限制。
@Configuration
class AsyncConfiguration implements AsyncConfigurer {
@Bean
protected WebMvcConfigurer webMvcConfigurer() {
return new WebMvcConfigurerAdapter() {
@Override
public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
configurer.setTaskExecutor([your task executor]);
}
};
}
}
Run Code Online (Sandbox Code Playgroud)
使用上面的配置来定义TaskExecutor适合您需要的配置并消除警告。
| 归档时间: |
|
| 查看次数: |
3262 次 |
| 最近记录: |