线上发现这个接口调用时间非常长 花费2min
java">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的变量 {前缀.} 前缀可以区分不同的listInputStream 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导致时间花费太长
排查这段代码的大对象是在循环里面大对象不停的被创建
java">Map<String, GetHistoryDataChildVO> collect = data1.stream().collect(Collectors.toMap(v -> DateUtil.formatDateTime(v.getDataTime()), Function.identity()));
优化之后时间明显缩短,将大对象单独只操作一次即可
java">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);}