查询时间过长导致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 文件会弹出到他们的收件箱中。
各位。我目前正在维护一个使用 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 文件会弹出到他们的收件箱中。