【问题标题】:File uploads from multiple clients slowing Java Spring application从多个客户端上传文件会降低 Java Spring 应用程序的速度
【发布时间】:2015-09-01 18:28:45
【问题描述】:

我有一个带有 Java Spring、mysql 后端和 AngularJS 前端的应用程序。它托管在 amazon ec2 m4.xlarge 实例上。

我使用 HTML5 相机捕捉功能拍摄照片并通过 RESTful Web 服务将 base64 编码图像和其他一些元数据发送到后端。在后端,我将 base64 数据转换为 png 文件并保存到磁盘,并在 MySQL 数据库中输入有关文件状态的条目。在许多用户开始同时上传图像之前,这一直运行良好。系统中有 4000 多个用户,在高峰期可能有大约 1000 个并发用户尝试同时上传图像数据。拥有太多用户会减慢我的应用程序的速度,并且需要 10-15 秒才能返回任何页面(通常不到 2 秒)。我检查了我的服务器统计数据,CPU 利用率低于 20%,并且没有使用 SWAP 内存。我不确定瓶颈在哪里以及如何衡量它。关于如何解决问题的任何建议?我知道自动缩放 ec2 并在后端的图像数据处理中排队可能会有所帮助,但在做任何事情之前,我想找到问题的根本原因。

处理base64图像的Java代码:

/**
 * POST  /rest/upload/studentImage -> Upload a photo of the user and update the Student (Student History and System Logs)
 */
@RequestMapping(value = "/rest/upload/studentImage",
    method = RequestMethod.POST,
    produces = "application/json")
@Timed
public Integer create(@RequestBody StudentPhotoDTO studentPhotoDTO) {
    log.debug("REST request to save Student : {}", studentPhotoDTO);
    Boolean success = false;
    Integer returnValue = 0;

    final String baseDirectory = "/Applications/MAMP/htdocs/studentPhotos/";

    Long studentId = studentPhotoDTO.getStudent().getStudentId();

    String base64Image = studentPhotoDTO.getImageData().split(",")[1];
    byte[] imageBytes = DatatypeConverter.parseBase64Binary(base64Image);
    try {
        BufferedImage image = ImageIO.read(new ByteArrayInputStream(imageBytes));

        String filePath = baseDirectory + 'somestring';
        log.info("Saving uploaded file to: " + filePath);

        File f = new File(filePath);
        Boolean bool = f.mkdirs();

        File outputfile = new File(filePath + studentId + ".png");
        success = ImageIO.write(image, "png", outputfile);

    } catch (IOException e) {
        success = false;
        e.printStackTrace();
    } catch(Exception ex){
        success = false;
        ex.printStackTrace();
    }

    if(success) {
        returnValue = 1;
        // update student
        studentPhotoDTO.getStudent().setPhotoAvailable(true);
        studentPhotoDTO.getStudent().setModifiedOn(new Date());

        studentRepository.save(studentPhotoDTO.getStudent());
    }
    return returnValue;
}

这是我的 cloudwatch 网络监控的图像

更新(2015 年 6 月 17 日):

我正在使用 ajp ProxyPass 为带有 apache 前端的 Spring Boot tomcat 应用程序提供服务。我尝试在没有 apache 前端的情况下直接为 tomcat 应用程序提供服务,这似乎显着提高了性能。我的应用程序没有像以前那样变慢。仍在寻找根本原因。

【问题讨论】:

  • 您是否检查了 VM 可用的原始网络吞吐量?
  • 我没有测试过自己,但是 aws 文档说专用 EBS 吞吐量 750 Mbps。对于我的应用程序,base64 图像每个大约 100kb,因此即使 1000 个用户同时尝试上传,它最大也会像 100Mb。或者我在这里错过了什么?我刚刚添加了cloudwatch监控的截图。
  • 不是 EBS,传入的 Internet 连接。
  • 对不起,我误解了。我可以使用一些帮助来衡量它。 AWS 说高,但对于确切的值,我可能需要使用一些我认为的工具。

标签: java mysql angularjs amazon-ec2 spring-boot


【解决方案1】:

我建议不要使用技术方法来解决这个问题,而是使用一个好的设计来解决这个问题。在我看来,完全基于您提供的信息使用,我认为这是一个设计问题。要找到这个问题的根本原因,我需要看看你的代码。

但就目前而言,一个设计应该是使用一个队列在后端处理图像,并在前端通知用户他们的图像已排队等待处理。一旦它被处理,它应该说它已经被处理(或者因为一些错误而没有被处理)。

如果你能显示代码,如果有问题,我可以尝试找出问题。

【讨论】:

  • 我同意。这很可能只是一个设计问题,并且由于时间紧迫,实施开始时是错误的。我想有一个队列机制,但没有到达那里。我已将负责后端 base64 blob 的代码粘贴到图像文件处理中。如果您有任何 cmets,请告诉我。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-10-24
  • 1970-01-01
  • 2022-08-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多