线上发现这个接口调用时间非常长 花费2min
public void exportExcel(GetHistoryDataDTO getHistoryDataDTO, HttpServletResponse httpResponse) {
List<Map<String, String>> dataList = new ArrayList<>();
getHistoryDataDTO.getGetHistoryDataChildren().get(0).setConfCode("COAGULANT_FLOW");
long l1 = System.currentTimeMillis();
List<GetHistoryDataVO> addAlumCompareData = this.getAddAlumCompareData(getHistoryDataDTO);
long l2 = System.currentTimeMillis();
log.info("==========exportExcel========= t1:{}", (l2 - l1) / 1000.0);
getHistoryDataDTO.getGetHistoryDataChildren().get(0).setConfCode("TURBIDITY_OUT");
List<GetHistoryDataVO> historyData = this.getHistoryData(getHistoryDataDTO);
long l3 = System.currentTimeMillis();
log.info("==========exportExcel========= t2:{}", (l3 - l2) / 1000.0);
Date currentTime = getHistoryDataDTO.getBeginTime();
while (currentTime.getTime() < getHistoryDataDTO.getEndTime().getTime()) {
String time = DateUtil.formatDateTime(currentTime);
Map<String, String> data = new HashMap<>();
data.put("time", time);
if (CollectionUtils.isNotEmpty(addAlumCompareData)) {
List<GetHistoryDataChildVO> data1 = addAlumCompareData.get(0).getData();
if (Objects.nonNull(data1)) {
Map<String, GetHistoryDataChildVO> collect = data1.stream().collect(Collectors.toMap(v -> DateUtil.formatDateTime(v.getDataTime()), Function.identity()));
GetHistoryDataChildVO vo = collect.get(time);
if (Objects.nonNull(vo)) {
BigDecimal addAlumFlowOneValue = vo.getOneActualValue();
data.put("addAlumFlowOneValue", addAlumFlowOneValue == null ? "" : addAlumFlowOneValue.toString());
BigDecimal addAlumFlowTwoValue = vo.getActualValue();
data.put("addAlumFlowTwoValue", vo.getActualValue() == null ? "" : addAlumFlowTwoValue.toString());
BigDecimal addAlumFlowPre = vo.getCalculatedValue();
data.put("addAlumFlowPre", vo.getCalculatedValue() == null ? "" : addAlumFlowPre.toString());
}
}
}
if (CollectionUtils.isNotEmpty(historyData)) {
List<GetHistoryDataChildVO> data1 = historyData.get(0).getData();
if (CollectionUtils.isNotEmpty(data1)) {
Map<String, GetHistoryDataChildVO> collect = data1.stream().collect(Collectors.toMap(v -> DateUtil.formatDateTime(v.getDataTime()), Function.identity()));
GetHistoryDataChildVO vo = collect.get(time);
if (Objects.nonNull(vo)) {
BigDecimal turbidityValue = vo.getActualValue();
data.put("turbidityValue", vo.getActualValue() == null ? "" : turbidityValue.toString());
BigDecimal turbidityValuePre = vo.getCalculatedValue();
data.put("turbidityValuePre", vo.getCalculatedValue() == null ? "" : turbidityValuePre.toString());
}
}
}
dataList.add(data);
currentTime = DateUtil.offsetMinute(currentTime, 2);
}
long l4 = System.currentTimeMillis();
log.info("==========exportExcel========= t3:{}", (l4 - l3) / 1000.0);
log.info("exportExcelMonth dto:{}", JSON.toJSONString(dataList));
ExcelWriter excelWriter = null;
Map<String, Object> extMap = new HashMap<>();
extMap.put("startTime", DateUtil.formatDateTime(getHistoryDataDTO.getBeginTime()));
extMap.put("endTime", DateUtil.formatDateTime(getHistoryDataDTO.getEndTime()));
ExcelUtil.configResponse(httpResponse);
// 模板注意 用{} 来表示你要用的变量 如果本来就有"{","}" 特殊字符 用"\{","\}"代替
// {} 代表普通变量 {.} 代表是list的变量 {前缀.} 前缀可以区分不同的list
InputStream inputStream = null;
File reportFile = null;
try {
inputStream = new ClassPathResource("template/addAlum.xlsx").getInputStream();
reportFile = new File("addAlum.xlsx");
FileUtils.copyInputStreamToFile(inputStream, reportFile);
excelWriter = EasyExcel.write(httpResponse.getOutputStream()).excelType(ExcelTypeEnum.XLSX).withTemplate(reportFile.getPath()).build();
WriteSheet writeSheet = EasyExcel.writerSheet().build();
// 简单的说 如果你的模板有list,且list不是最后一行,下面还有数据需要填充 就必须设置 forceNewRow=true 但是这个就会把所有数据放到内存
FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).direction(WriteDirectionEnum.VERTICAL).build();
//填充列表数据
excelWriter.fill(extMap, fillConfig, writeSheet);
//log.info("exportExcelMonth dataList:{}", JSON.toJSONString(dataList));
if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(dataList)) {
excelWriter.fill(dataList, fillConfig, writeSheet);
}
} catch (Exception e) {
e.printStackTrace();
log.error("导出异常:{}", e.getMessage());
} finally {
if (Objects.nonNull(reportFile) && reportFile.exists()) {
boolean delete = reportFile.delete();
log.info("文件删除" + (delete ? "成功" : "失败"));
}
// 千万别忘记close 会帮忙关闭流
if (excelWriter != null) {
excelWriter.finish();
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
log.error("文件流异常", e);
}
}
}
long l5 = System.currentTimeMillis();
log.info("==========exportExcel========= t4:{}", (l5 - l4) / 1000.0);
}在这里插入代码片
打日志排查后发现问题出在t3,是循环里的代码花费的时间太长。
在服务上查看jvm状态发现在调用时不停的进行young gc导致时间花费太长
排查这段代码的大对象是在循环里面大对象不停的被创建
Map<String, GetHistoryDataChildVO> collect = data1.stream().collect(Collectors.toMap(v -> DateUtil.formatDateTime(v.getDataTime()), Function.identity()));
优化之后时间明显缩短,将大对象单独只操作一次即可
if (CollectionUtils.isNotEmpty(addAlumCompareData)) {
List<GetHistoryDataChildVO> data1 = addAlumCompareData.get(0).getData();
if (Objects.nonNull(data1)) {
data1.forEach(v -> addAlumMap.put(DateUtil.formatDateTime(v.getDataTime()), v));
}
}
if (CollectionUtils.isNotEmpty(historyData)) {
List<GetHistoryDataChildVO> data1 = historyData.get(0).getData();
if (Objects.nonNull(data1)) {
data1.forEach(v -> turbidityMap.put(DateUtil.formatDateTime(v.getDataTime()), v));
}
}
while (currentTime.getTime() < getHistoryDataDTO.getEndTime().getTime()) {
String time = DateUtil.formatDateTime(currentTime);
Map<String, String> data = new HashMap<>();
data.put("time", time);
GetHistoryDataChildVO vo = addAlumMap.get(time);
if (Objects.nonNull(vo)) {
BigDecimal addAlumFlowOneValue = vo.getOneActualValue();
data.put("addAlumFlowOneValue", addAlumFlowOneValue == null ? "" : addAlumFlowOneValue.toString());
BigDecimal addAlumFlowTwoValue = vo.getActualValue();
data.put("addAlumFlowTwoValue", vo.getActualValue() == null ? "" : addAlumFlowTwoValue.toString());
BigDecimal addAlumFlowPre = vo.getCalculatedValue();
data.put("addAlumFlowPre", vo.getCalculatedValue() == null ? "" : addAlumFlowPre.toString());
}
GetHistoryDataChildVO turbidity = turbidityMap.get(time);
if (Objects.nonNull(turbidity)) {
BigDecimal turbidityValue = turbidity.getActualValue();
data.put("turbidityValue", turbidity.getActualValue() == null ? "" : turbidityValue.toString());
BigDecimal turbidityValuePre = turbidity.getCalculatedValue();
data.put("turbidityValuePre", turbidity.getCalculatedValue() == null ? "" : turbidityValuePre.toString());
}
dataList.add(data);
currentTime = DateUtil.offsetMinute(currentTime, 2);
}