查询花费很长时间导致504超时错误?

时间:2018-10-20 14:52:05

标签: java oracle http http-status-code-504

每个人。我目前正在使用struts2和hibernate维护旧系统。有一个功能是在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;
}

1 个答案:

答案 0 :(得分:1)

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

  

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

显然是外部电话。几乎所有的时间都是TTFB。但是您仍然不知道那段时间实际上在哪里。

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

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

如果大部分时间都花在数据检索上,则需要查看数据库查询(或其他查询)并尝试对其进行调优。

很明显,我在提出这些建议时并不了解您的组织或您的职责/权限。如果外部服务确实是外部服务,则您可能无法获得改进。

替代解决方案?

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