首页 > 解决方案 > 使用 Spring Boot API 进行文件上传的 Tomcat 性能

问题描述

我有一个 Spring Boot API,其中一个端点允许用户上传视频。现在,我的控制器基本上将该文件作为 MultiPart 文件,然后将其存储在 tomcat 可访问的临时文件夹中。将其存储在磁盘上后,我会将视频推送到 S3 存储桶。

无论如何,现在对我来说,这似乎不是最佳的,就像我想一次上传 100 或 1000 个用户一样,首先将文件写入磁盘似乎真的没有性能。

作为一点背景,我将它存储在磁盘上,目的是如果推送到 S3 时出现问题,我可以重试

下面的代码可能会显示我比上面做得更好:

public Video addVideo(@RequestParam("title") String title,
    @RequestParam("Description") String Description,
    @RequestParam(value = "file", required = true) MultipartFile file) {         
           this.amazonS3ClientService.uploadFileToS3Bucket(file, title, description));
}

视频文件存储方法:

String fileNameWithExtenstion = awsS3FileName + "." + FilenameUtils.getExtension(multipartFile.getOriginalFilename());

//creating the file in the server (temporarily)
File file = new File(tomcatTempDir + fileNameWithExtenstion);FileOutputStream fos = new FileOutputStream(file);

fos.write(multipartFile.getBytes());

fos.close();PutObjectRequest putObjectRequest = new PutObjectRequest(this.awsS3Bucket, awsS3BucketFolder + UnigueId + "/" + fileNameWithExtenstion, file);

if (enablePublicReadAccess) {
    putObjectRequest.withCannedAcl(CannedAccessControlList.PublicRead);
}

// Upload a file as a new object with ContentType and title 

specified.amazonS3.putObject(putObjectRequest);
//removing the file created in the server
file.delete();

所以我的问题是....在 Tomcat 中是否有更好的方法来:

A) 通过控制器接收文件B) 推送到 S3

标签: springspring-bootperformancetomcatamazon-s3

解决方案


没有其他方法可以使用多部分来做到这一点。multipart 的问题是从他们需要的请求中正确分割部分有时会被跳过或可重复。如果没有内存爆炸,那在内存中是不可能的。因此,Commons FileUpload 在达到某个阈值后会将它们缓存在磁盘上。多部分请求是最糟糕的方式。我强烈建议使用其中一个PUTPOST与 content type一起使用application/octet-stream。您可以获取裸请求输入流并传递给 HttpClient 以流式传输到您的后端服务器。我在 5 年前就已经这样做了,它适用于千兆字节。我已经在 Apache HttpClient 邮件列表中发布了解决方案。

有一种可能性是在特定条件下如何工作:

  • 所有部分都按照您要阅读的正确物理顺序
  • 您对后端的写入速度足以支持从前端读取

消耗根部分,然后转到下一个物理部分,懒惰地处理请求体。JAX-WS RI (Metro) 可以很好地处理 XOP/MTOM 的多部分请求。从中吸取教训,因为你无法让它变得更好。


推荐阅读