由excel导出引起的cpu 100% 和gc 的问题
大家好,我是烤鴨:
?? ?記一次 由excel導出 導致的cpu飆升200%,jvm 內存不足。
1. ?場景復現
?? ?前端頁面導出Excel,之前導出4,5W條數據都沒什么問題的。
?? ?今天業務突然反饋說導出不了了,我試著導出了2w數據,發現頁面卡住了,
?? ?沒有響應了,查日志,報錯如下。
? ? ?查看了導出方法,發現如果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; charset=utf-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單元格的時候,沒有判斷樣式是否存在,
??只要是空單元格,就新創建一個單元格樣式。
??改之前:
? 改之后:
if (val != null){CellStyle style = styles.get("data_column_"+column);if (style == null){style = wb.createCellStyle();style.cloneStyleFrom(styles.get("data"+(align>=1&&align<=3?align:"")));style.setDataFormat(wb.createDataFormat().getFormat(cellFormatString));styles.put("data_column_" + column, style);}cell.setCellStyle(style);}? ? 不要小瞧了這個判空,原來的寫法會多創建2w行*20列=40w個對象,導致各個空間的滿了原因。
?? ?如果還沒找到問題的話,就輸出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 pid>xxx.logs
?
總結
以上是生活随笔為你收集整理的由excel导出引起的cpu 100% 和gc 的问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 从零开始,做一个NodeJS博客(四):
- 下一篇: CentOS离线安装gcc环境(附安装包