java - Java Spring 和 Tomcat 并发文件下载速度慢

标签 java spring spring-mvc tomcat optimization

我开发了一个提供 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 bean?或者是访问磁盘的 I/O 问题?该系统位于 AWS EC2 虚拟机上。

最佳答案

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

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

看看这个post还有这个post了解更多信息

关于java - Java Spring 和 Tomcat 并发文件下载速度慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46522390/

相关文章:

java - 如何获取用户输入的数字并分配给字节

java - 使用 Spring Boot 的 OAuth2 SSO,无需授权屏幕

java - jackson : NoSuchMethodError for org. codehaus.jackson.map.DeserializationConfig.withAnnotationIntrospector

java - 如何在 Spring boot 下运行的 REST Controller 中获取与 HTTPS 请求相关的 SSL 证书(X.509)?

java - 应用根路径

javascript - 从 java 文件中的函数弹出简单的文本消息警报

java - 使用 Arrays.sort 对数组元素进行排序

java - 如何从一个范围中随机获取 double 值

java - Spring运行独立线程

java - 带有拉丁字符的阅读器属性文件