您的位置:首页 > 其它

线上服务经常性死机问题分析总结

2012-11-29 16:10 218 查看


问题描述

超影网站系统经常莫名奇妙的就不响应,特别是当发布一些活动后访问数量比平时多的时候这种情况尤为突出,表现为用户不能访问网站,需要重新启动服务才能够解决。


[编辑]问题解决步骤


[编辑]初步把脉

登录线上服务器后发现tomcat实例并没有死掉,依然还存在,cpu、内存耗费的也不大,80端口依然被占用,通过浏览器输入http://localhost 不响应,但telnet
localhost 80会返回信息。
试图去寻找相关日志,tomcat_home/logs下没有任何日志,试图使用jvisualvm查看tomcat内存和线程状况,但在jdk目录下却找不到这个工具。试图使用jps和jstat工具,但不能发现java进程id。
猜测是内存配置太小或者线程死锁问题,但没有证据支持。试图修改catalina.bat配置新的虚拟机内存,配置重启后,依然会出现死机问题,通过任务管理器发现tomcat进程内存不超过150m,也没有记录下jvm gc日志。配置为
-Xms1024m -Xmx1024m -Xmn512m -XX:PermSize=64M -Xmn=400m -XX:MaxPermSize=128m  -XX:+PrintGCDetails  -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps  -Xloggc:D:\gclog\gc.log


百思不得其解,仔细观察系统的部署方式,发现和官方推荐的方法不同,是通过自己写的bat脚本实现,脚本中自行调用java -jar的模式启动,其配置的最大内存值是100m,这就解释了为什么任务管理器里tomcat只占不到150m了和在catalina.bat里配置的java参数完全不起作用了。接下来通过在install-bos.bat脚本中指定jvm参数配置大内存:
-Xms900m -Xmx900m -Xmn500m -XX:PermSize=64M -XX:MaxPermSize=128m -XX:+PrintGCDetails -XX:+PrintGCTimeStamps  -Xloggc:D:\gclog\gc.log

这样终于可以看到gc日志了。通过日志分析,发现目前线上jdk的版本比较低,没有server版本,gc采用序列化方式。
通过初步配置大内存,系统稳定了许多,但是司机现象依然存在,只是出现的频率小了,怀疑有数据库慢查询,通过开启数据库的慢查询日志,发现大量慢查询语句,这些语1句基本都处理影片屏蔽功能的,需要解决这些慢查询。
分析这些慢查询语句,发现有两个问题:

select处理过多的字段,特别是影片简介字段,很长但在页面显示时却并不这些数据,占很多内存空间,这样可能造成年轻代gc频繁,当用户量大时,年轻代频繁gc造成老领代暴增,最终造成full gc,但大量页面请求还没有完成,内存数据依然在不能被gc,所以频繁full gc。
频繁select,多个方法其实使用大致相同的数据,完全可以一次读取所有数据,在多个方法中传递使用,降低select和数据对象构造的频率,从而降低gc频率。


[编辑]深度研究

为了彻底解决这个问题,特地部署测试机,采用jdk64位最新版+tomcat6 64位版本,采用官方推荐模式部署,然后通过loadrunner做压力测试

首次测试,并发50人,压10分钟即崩溃,分析发现,这次测试时使用windows service模式部署tomcat,造成catalina.bat的jvm配置参数无效,研究发现,以windows service模式部署时,jvm参数配置需要在service.bat中配置:
set Jvm_Options="-XX:NewSize=512m;-XX:MaxPermSize=128m;-XX:+PrintGCDateStamps;-XX:+PrintGCTimeStamps;-XX:+PrintGCDetails;-XX:+PrintTenuringDistribution;-Xloggc:e:/gclog/gc.log"

"%EXECUTABLE%" //US//%SERVICE_NAME% ++JvmOptions %Jvm_Options% %Debug_Options%  "-DRootPath=%CATALINA_HOME%\webapps";-Duser.dir=%CATALINA_HOME%;-Djava.io.tmpdir=%CATALINA_BASE%\temp;-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager;-Djava.util.logging.config.file=%CATALINA_BASE%\conf\logging.properties" --JvmMs 1024 --JvmMx 1024

"-DRootPath=%CATALINA_HOME%\webapps";-Duser.dir=%CATALINA_HOME%是目前系统初始化需要的目录配置

--JvmMs 1024 --JvmMx 1024是jvm内存配置


再次压测,50人10分钟即崩溃,分析gc日志,年轻代的gc频繁,老龄代上涨迅速,有一段时间持续full gc,每次都不能释放内存,持续full gc造成程序不响应,猜测内存泄漏,查找代码视图发现有泄漏的静态变量,但未发现泄漏点,通过jstat分析tomcat进程内存,发现1小时内不再访问系统,内存会逐渐降下来,所以分析,没有内存泄漏点,是gc频率造成。
慢查询解决后压测,本次测试使用50并发,压测1小时,系统响应响应,但会出现数据库连接失败异常。分析应该系统访问数据库没有使用连接池,而是直接使用jdbc连接造成的。
到此为止,需要解决的问题就只剩下数据库连接池问题了。试图使用jndi来实现连接池:

乱码问题,曾经试图使用过jndi连接池,但发现数据乱码,不能解决,一般google的结果是在数据库url中增加characterEncoding=utf-8即可解决,如果有问题,把'&'修改为'&',即可,但我们的却不行,分析发现系统使用的jdbc驱动是3.x.x版本,但数据库是5.0版本,猜测是jdbc驱动不匹配,换成5.0.8解决乱码问题。
日期型数据问题,乱码问题解决后,发了日期型数据处理有问题,当数据库datetime字段为0时,系统报不能把'0000-00-00 00:00:00'转化为datetime异常,但在jdbc3.x.x下没有问题,应该是换jdbc驱动造成的,经过google发现,在url上增加zeroDateTimeBehavior=convertToNull即可解决。

再次压力测试还没有开始,5月14号后需要再次测试。


[编辑]反思

日志问题。日志是系统出现故障时,程序员分析、解决问题的利器。监控、转储进程内存堆栈并记录成文件应该是每个程序员必备的技能,开发新系统时定义结构良好的日志子系统更是架构师必须的责任。日志是如此的重要,但我们的系统无论是tomcat的日志还是系统的日志都没有记录,或者记录的是没有价值的。程序中到处可见捕获异常后没有输入堆栈而直接定义一个新的异常抛出的代码,这种代码抛弃了系统异常的第一手资料。
部署问题,系统的部署完全无视tomcat官方推荐的部署方案,纯粹的自定义,增加了解决问题的难度
代码精炼问题,代码基于的数据库访问框架有很多代码与我们的业务没有关系,应该剔除


[编辑]其他

配置某一应用为tomcat的缺省应用:

删除webapps下原来的所有应用
删除conf/catalina下所有
server.xml中Host元素下添加
<Context>path="" docBase="/WebApp" reloadable="true" crossContext="true" </Context>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: