查询时间过长导致504超时错误?

The query takes a long time result in a 504 timeout error?

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

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

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

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

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

    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;
}

这不是真正的答案,但对于评论来说太长了。

I thought the main problem is the external requests.

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

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

如果大部分时间花在网络通话上(除非您可以说服您的网络管理员线路有问题),您除了减少通话次数外别无他法。也就是说,使用接受和 return bulk bulk payloads 的服务扩展远程接口。

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

很明显,我在对您的组织或您的 responsibilities/authority 一无所知的情况下提出这些建议。如果外部服务是真正的外部服务,您可能无法获得改进。

替代解决方案?

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