首页 > 其他分享 >excel导出大数据量时服务器cpu过高tomcat卡死问题排查

excel导出大数据量时服务器cpu过高tomcat卡死问题排查

时间:2022-09-22 16:33:28浏览次数:84  
标签:tomcat excel 导出 gc 数据量 日志 cpu

  最近发现一套线上生产系统每周一都会出现宕机的现象,CPU很高,持续几分钟后tomcat直接卡死,系统无法登陆刷新无反应,重启后又回复正常,各种定位各种检查。最开始想到的是不是有啥挖矿程序每周一自动启动挖矿,所以先后扫描了服务器检查了定时任务都没有发现问题。后来在检查tomcat的访问日志(localhost_access_log.yyyy-MM-dd.txt)发现每周一都有人在我的服务器上大量导出excel,导出的时间点和服务器CPU爆满,磁盘读写这些时间点刚好吻合:

cpu使用率爆满

tomcat的localhost_access_log日志

     看到这里我就猜想可能是excel导出模块程序没有处理好,在导出大量数据的时候内存溢出,tomcat卡死;检查了一下导出前的查询日志,发现导出前用户查询到的数据是12000条左右,立马在本地模拟测试一下发现tomcat在第二次执行导出的时候就直接卡死,eclipse也直接提示error :Unhandled event loop exception Java heap space,基本上就证实了我的猜想。剩下的问题就是怎么解决这个问题。

    我的服务器环境是CentOS7.6, 64位 4核,8G内存,tomcat7, poi3.6.jar. 大概在12000条数据的excel导出就卡死。设置jvm参数已经是设置到最大了,没办法再往上加内存分配了。第一阶段我做了如下几个优化处理:

  1. 1、将页面的导出按钮在点击导出后立即置灰,待下载完成后等待几秒后恢复可点击;防止用户再等待过程中多次点击。
  2. 2、使用js禁止用户刷新导出操作页面(效果不是很明显)
  3. 3、网上传说poi最新版本4.0已经优化了这种问题,可以升级尝试一下:http://poi.apache.org/  (前提是最低支持JAVA8)
  4. 4、代码优化:将导出过程中数据日志减少,减少对象的新建(new 新对象),必要的对象放在循环外new。变量声明到底在循环外部能有效的降低耗时        和内存消耗;还有一个就是一定要关闭流输出fout.flush();fout.close();
  5. 5、跟需求方商量将excel导出上限设定在10000条记录左右。

第一阶段我就做了这些优化处理,目前效果还在观察中,如有新问题或者进展后续更新。

 

 

 

 

大家好,我是烤鸭:
    记一次 由excel导出 导致的cpu飙升200%,jvm 内存不足。

1.  场景复现


    前端页面导出Excel,之前导出4,5W条数据都没什么问题的。
    今天业务突然反馈说导出不了了,我试着导出了2w数据,发现页面卡住了,
    没有响应了,查日志,报错如下。

java.lang.IllegalStateException: Cannot call sendRedirect() after the response has been committed
	at 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; 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单元格的时候,没有判断样式是否存在,
  只要是空单元格,就新创建一个单元格样式。
  改之前:

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"+(align>=1&&align<=3?align:"")));
	        style.setDataFormat(wb.createDataFormat().getFormat(cellFormatString));
			styles.put("data_column_" + column, style);
		}
		cell.setCellStyle(style);
	}

    不要小瞧了这个判空,原来的写法会多创建2w行*20列=40w个对象,导致各个空间的满了原因。
    如果还没找到问题的话,就输出gc日志,慢慢查。

jmap -histo 9021>xxx.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 pid>xxx.logs

 

 

 

 

参考:由excel导出引起的cpu 100% 和gc 的问题

参考:excel导出大数据量时服务器cpu过高tomcat卡死问题排查

标签:tomcat,excel,导出,gc,数据量,日志,cpu
From: https://www.cnblogs.com/aspirant/p/16719814.html

相关文章

  • delphi TMS FlexCel 导出HTML
    TMSFlexCel导出HTML属性和方法TFlexCelHtmlExport用于将Excel文件导出为HTML的组件。unitFlexCel.RenderTFlexCelHtmlExport.CreateconstructorCreate(const......
  • tomcat server.xml标签功能详解
    1.具体说明  tomcat/conf/server.xml<!--属性说明port:指定一个端口,这个端口负责监听关闭Tomcat的请求shutdown:向以上端口发送的关闭服务器的命令字符串--><Se......
  • 前端 excel 表格导出
    传统的表格导出是直接获取数据,传表头,数据,自动下载表格。Blob.js和 Export2Excel.js 如果要导出这样的表格,那么需要重新写一个方法,核心在于  {s:{r:行开始,c:列......
  • Tomcat not-working报错解决方式
    JDK版本指定错误需要指定JREJDK结构 这种需要安装特定的jdk后tomcat指定特定的jdkcat/usr/local/tomcat6/bin/catalina.sh设置全局变量exportJAVA_HOME=/usr/loc......
  • idea 打包war成功,在tomcat下运行的时候也不报错,但是访问不到,直接报404
    修改pom文件,打war包成功,在tomcat下运行的时候也不报错,但是访问不到,直接报404,后来找到原因:需要在application启动类继承SpringBootServletInitializer,查了一个这个类,就是......
  • Linux安装tomcat后启动报错Cannot find ./catalina.sh的解决方法
    Linux安装tomcat后启动报错:Cannotfind./catalina.shThefileisabsentordoesnothaveexecutepermissionThisfileisneededtorunthisprogram原因:无权限解......
  • 30套各行业可视化模板,比Excel好看千倍!
    可视化大屏的目的是通过将数据在屏幕上可视化,帮助用户熟悉业务数据,以便于高效地处理信息、快速做出应答。 以下行业案例模板均来源于:山海鲸可视化  1. 医疗行业进......
  • Tomcat乱码问题
    Tomcat乱码解决方法一更改conf/logging.properties中的UTF-8为GBK但是这种更改只会更改日志乱码,sout控制台输出依旧是乱码。方法二更改idea配置bin/idea.exe.vmopti......
  • pandas 读取 excel 时指定某些列
    单列其中B就代表excel表中的列索引standard_word=pd.read_excel('合并.xlsx',usecols='B')多列其中C:AK就代表excel表中的列索引generalized_word=pd.read_exce......
  • Excel 错误:部分地区不支持使用地图
    问题描述:在用excel2019版做地图时,不能使用地图图表? 解决办法:原因分析:微软部分服务对国家和地区有限制,改为支持服务的地区就可以使用了。所以,将电脑......