使用 Java Spring 和 Tomcat 下载并发文件的速度较慢



我开发了一个提供REST的Spring MVC项目。 其中一个方法返回数据的 zip 文件。如果数据包很小(小于 10MB)或我们收到的连接很少,响应时间还可以,但是如果我有一个 20MB 的文件或一百个请求,那就很慢了。这是我的代码:

@RequestMapping(value = "{venue}/packet", method = RequestMethod.GET)
public ResponseEntity getPackage(@PathVariable("venue") int id,
@RequestParam(value = "reqid", required = false) int reqid,
@RequestParam(value = "version", required = false, defaultValue = "1.0") String version,
@ModelAttribute("user") Developer user, HttpServletRequest request, HttpServletResponse resp) {
String req_code = "[" + Thread.currentThread().getId() + "] ";
long start = System.currentTimeMillis();
// Check if the version of the client is already updated
if (!version.equals(venue.getVersion())) {
//Returns a file from File System
File zipped = venueService.getPacket(venue);
resp.setContentType("application/zip");
resp.setContentLength((int) zipped.length());
resp.setHeader("Content-Disposition", "attachment;filename=" + zipped.getName());
try {
InputStream is = new BufferedInputStream(new FileInputStream(zipped));
long copytime = System.currentTimeMillis();
packet_log.info(req_code + "Start copy req:" + reqid);
IOUtils.copy(is, resp.getOutputStream());
resp.flushBuffer();
is.close();
packet_log.info(req_code + "End copy req:" + reqid + " in " + (System.currentTimeMillis() - copytime));
} catch (IOException e) {
e.printStackTrace();
}
long dur = System.currentTimeMillis() - start;
packet_log.info(req_code + "Send to client req:" + reqid + " in " + dur / 1000);
packet_log.info("");
return new ResponseEntity<Object>("", headers, HttpStatus.OK);
}

我插入了很多日志和一个由客户端和服务器共享的"reqid"参数来监视每个请求。 当我有多个并发请求时,命令IOUtils.copy(is, resp.getOutputStream());变得非常慢。如果我发送 80 个请求,复制一个 20MB 的文件需要一分钟以上。

我认为我的代码没有问题。也许这取决于Spring MVC如何管理@RestController豆子?还是访问磁盘的 I/O 问题?系统位于 AWS EC2 虚拟机上。

你实现的是一种通过直接写入HttpServletResponseOutputStream来下载文件的阻止方式。

如果您使用的是Spring 4.2+,则可以返回一个StreamingResponseBody该将文件字节异步流式传输到接收客户端。

看看这篇文章和这篇文章以获取更多信息

而不是使用IOUtils.copy(is, resp.getOutputStream());将文件的输入流复制到HttpServletResponse的输出流,而是使用FileSystemResource客户端下载您的 zip 文件。

public FileSystemResource downloadFile(HttpServletResponse response) {
File file = new File("BASE_PATH/MY_ZIP_FILE.zip");
response.setContentType("application/zip");      
response.setHeader("Content-Disposition", "attachment; filename="+"MY_ZIP_FILE.zip");
return new FileSystemResource(file); 
}

相关内容

  • 没有找到相关文章

最新更新