java - 查询需要很长时间导致 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;
}
解决方案
这不是一个真正的答案,但评论太长了。
我认为主要问题是外部请求。
显然是外部调用。几乎所有花费的时间都是TTFB。但是你仍然不知道那个时间到底去哪儿了。
基本上是三种成本。首先是执行代码、格式化请求和解析响应的成本。由于这似乎可以忽略不计,我们可以继续前进。第二个是执行调用的固定成本:通过网络发送内容。这是您支付 6000 倍的通行费。第三是检索数据的成本:这也是你支付 6000 倍的费用,但根据数据源的不同,成本可能不是固定的(例如,数据库缓存可以抵消重复查询)。
如果大部分时间都花在网络通话上,那么(除非你能说服你的网络管理员,线路有问题),除了减少通话次数之外,你无能为力。也就是说,使用接受和返回大容量负载的服务扩展远程接口。
如果大部分时间都花在数据检索上,您需要查看数据库查询(或其他)并尝试调整它们。
显然,我在不了解您的组织或您的职责/权限的情况下提出这些建议。如果外部服务是真正的外部服务,您可能无法获得改进。
替代解决方案?
- 并发处理:有多个线程调用远程服务器。您将需要重写您的代码,但至少这是在您的控制之下。
- 增加超时时间:给你的程序更多的时间来完成。但是,假设成本是线性的,处理 3000 对呼叫将需要 10 分钟。您的用户可能不希望他们的屏幕挂起那么久。所以...
- 异步提交。用户发出请求,继续下一个任务,一段时间后,完成的 Excel 文件弹出到他们的收件箱中。
推荐阅读
- django-rest-framework - 如何仅将另一个序列化程序用于 CREATE 响应?
- javascript - JQuery按选择值隐藏行中的字段
- python - doctest 失败,没有显示统一的差异
- keycloak - 如何将元数据库与 Keycloak 连接?
- objective-c - 如何在 Objective-C 中比较 unsigned char?
- java - 如何使用缓冲流 I/O Java 从文本文件中搜索关键字列表
- ios - Swift-如何将单元格项目的数量划分为部分?
- php - 如何在 Laravel Livewire 中传递隐藏的表单输入?
- taleo - 如何在候选实体中检索 UDF 字段的特定值
- node.js - 将 azure blob 流下载到 zip nodejs