首页 > 解决方案 > 查询需要很长时间导致 504 超时错误?

问题描述

每个人。我目前正在使用struts2 和hibernate 维护一个旧系统。Excel中有一个功能是格式化数据,然后根据查询参数下载。通常每天增加3000条记录,通常我们只需要查看今天的数据,在Excel格式中减少了大约3000条记录。

它工作正常。然后我有一个新的需求,对于每条记录,我需要获取关于该记录的两个位置信息。好吧,我们的数据库中不存在位置信息。我需要请求两个接口来获取它们。我只是在for循环中执行此操作,即当我从数据库返回数据时,然后循环遍历数组列表,对于每条记录,请求它需要的两个位置信息。直到我收到所有消息,然后我在 Excel 中将它们格式化,然后响应前端。

问题是,服务器响应太慢。当它大约 200、300 条记录时,它工作正常。但是当涉及到 3000 条记录时,我收到了 504 超时错误。

我不认为 3000 条记录很大,但我认为对于发送请求的每条记录然后解析响应消息是耗时的。我认为我做错了,但我没有处理这种情况的经验。那么,我能得到一些建议吗?提前致谢。

编辑:我在下载200条记录时记录时间,有和没有外部请求,以及这里的伪代码。我认为外部请求是主要原因。 有外部请求 有外部请求 有外部请求 没有外部请求 没有外部请求 没有外部请求

    public byte[] methodName() {

  // 13 title
  String[] title = { "title1", "title2", "title3", ... , "title13" };
  // result is the records returned from db select
  String[][] data = new String[result.size()*20][title.length];

  int row = 0, col = 0;

  SomeEntity someEntity = null;

  System.out.println("with external requests");
  System.out.println("before loop-->" + System.currentTimeMillis() + " - " + new Date().toString());

  for (Object object : result) {
    someEntity = (SomeEntity) object;
    col = 0;
    data[row][col++] = someEntity.getTitle1();
    data[row][col++] = someEntity.getTitle2();
    // add other data
    ...
    // get location, two similar requests
    data[row][col++] = getXXXLocation(someEntity.getLongitude(), someEntity.getLatitude());
    data[row][col++] = getXXXLocation(someEntity.getMctId(), someEntity.getTerId());
    row++;
  }
  // then generate the ExcelModel
  System.out.println("after loop-->" + System.currentTimeMillis() + " - " + new Date().toString());
  ExcelModel excelModel = new ExcelModel("filename");
  excelModel.addColumnsTitle(title);
  System.out.println("before generate excel-->" + System.currentTimeMillis() + " - " + new Date().toString());
  byte[] aws = excelModel.generateExcelFile(data);
  System.out.println("after generate excel-->" + System.currentTimeMillis() + " - " + new Date().toString());

  return aws;
}

标签: javaoraclehttphttp-status-code-504

解决方案


这不是一个真正的答案,但评论太长了。

我认为主要问题是外部请求。

显然是外部调用。几乎所有花费的时间都是TTFB。但是你仍然不知道那个时间到底去哪儿了。

基本上是三种成本。首先是执行代码、格式化请求和解析响应的成本。由于这似乎可以忽略不计,我们可以继续前进。第二个是执行调用的固定成本:通过网络发送内容。这是您支付 6000 倍的通行费。第三是检索数据的成本:这也是你支付 6000 倍的费用,但根据数据源的不同,成本可能不是固定的(例如,数据库缓存可以抵消重复查询)。

如果大部分时间都花在网络通话上,那么(除非你能说服你的网络管理员,线路有问题),除了减少通话次数之外,你无能为力。也就是说,使用接受和返回大容量负载的服务扩展远程接口。

如果大部分时间都花在数据检索上,您需要查看数据库查询(或其他)并尝试调整它们。

显然,我在不了解您的组织或您的职责/权限的情况下提出这些建议。如果外部服务是真正的外部服务,您可能无法获得改进。

替代解决方案?

  • 并发处理:有多个线程调用远程服务器。您将需要重写您的代码,但至少这是在您的控制之下。
  • 增加超时时间:给你的程序更多的时间来完成。但是,假设成本是线性的,处理 3000 对呼叫将需要 10 分钟。您的用户可能不希望他们的屏幕挂起那么久。所以...
  • 异步提交。用户发出请求,继续下一个任务,一段时间后,完成的 Excel 文件弹出到他们的收件箱中。

推荐阅读