做宝宝衣服的网站,网站设计的初衷,做竞价网站用什么系统好,上海传媒公司ceo是谁大家好#xff0c;我是烤鸭#xff1a; 记一次 由excel导出 导致的cpu飙升200%#xff0c;jvm 内存不足。
1. 场景复现 前端页面导出Excel#xff0c;之前导出4,5W条数据都没什么问题的。 今天业务突然反馈说导出不了了#xff0c;我试着导出了2w数据#xff0…大家好我是烤鸭 记一次 由excel导出 导致的cpu飙升200%jvm 内存不足。
1. 场景复现 前端页面导出Excel之前导出4,5W条数据都没什么问题的。 今天业务突然反馈说导出不了了我试着导出了2w数据发现页面卡住了 没有响应了查日志报错如下。
java.lang.IllegalStateException: Cannot call sendRedirect() after the response has been committedat org.apache.catalina.connector.ResponseFacade.sendRedirect(ResponseFacade.java:488)at javax.servlet.http.HttpServletResponseWrapper.sendRedirect(HttpServletResponseWrapper.java:138) 查看了导出方法发现如果repsonse在响应过程中抛出异常的话就会有类似的问题。 正常的话因为需要把错误信息带到页面catch之后再return到对应的页面。 但如果是上图所示的write方法如果这地方报异常就会出现 Cannot call sendRedirect() after the response has been committed 的异常。 输出文件的代码如下如果这时候异常。
/*** 输出到客户端* param fileName 输出文件名*/public ExportExcel write(HttpServletResponse response, String fileName) throws IOException{response.reset();response.setContentType(application/octet-stream; charsetutf-8);response.setHeader(Content-Disposition, attachment;fileName new String(fileName.getBytes(GBK), iso-8859-1)); //中文文件名处理write(response.getOutputStream());return this;} 知道这是写法的问题但是并没有什么好的办法解决。 因为 异常需要通过addMessage(redirectAttributes, e.getMessage()) 带到重定向的页面。 但是转念一想这个问题不应该在这地方出现因为之前用了很长时间是没有这个问题的。
2. 寻找问题 再次执行导出的时候监测了一下cpu为啥第六感吧。
top #查看cpu进程运行
ps -ef|grep tomcat_xxx #查看tomcat 的 pid pid 是 19021 发现 19021 的进程爆表了...如下图 jstat -gcutil 19021 5000 #每隔5秒打印一次gc 又去看了gc的情况每隔5秒打印一次gc各个空间全都满了。而且YGC和FGC的频次和时间在迅速增加。(下图中的时间还没到满的时候后来确实都100了) 还好服务器还撑得住应该是数据量不是特别大没有报java.lang.OutOfMemoryError。
jmap -heap 19021 #查看堆内存详细信息
jstack 19021 #查看线程问题是否死锁 其实我的问题在这就解决了想了想最近改动过的代码基本就锁定了问题导出时候的问题 后来查了excel工具类的代码提交发现在创建cell单元格的时候没有判断样式是否存在 只要是空单元格就新创建一个单元格样式。 改之前
CellStyle style wb.createCellStyle();
cell.setCellStyle(style); 改之后 if (val ! null){CellStyle style styles.get(data_column_column);if (style null){style wb.createCellStyle();style.cloneStyleFrom(styles.get(data(align1align3?align:)));style.setDataFormat(wb.createDataFormat().getFormat(cellFormatString));styles.put(data_column_ column, style);}cell.setCellStyle(style);} 不要小瞧了这个判空原来的写法会多创建2w行*20列40w个对象导致各个空间的满了原因。 如果还没找到问题的话就输出gc日志慢慢查。
jmap -histo 9021xxx.log #输出gc日志到文件 3. 总结 如果是gc或者内存问题。 获取当前进程pid ps -ef|grep tomcat_xxx 或者 ps -ef|grep java 或者 jps 查看cpu利用率 top 监测gc jstat -gcutil pid 5000 查看堆内存详细信息 jmap -heap pid 查看是否死锁情况 jstack pid 还找不到的话输出gc的日志慢慢找 jmap -histo pidxxx.logs