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

本文详细记录了解决超影网站系统在高并发访问下的性能问题,包括调整Tomcat内存配置、优化数据库查询、部署环境优化及解决JDBC驱动与数据库版本不匹配等问题,最终通过引入连接池技术解决数据库连接问题,实现系统稳定运行。

问题描述

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

[编辑]问题解决步骤

[编辑]初步把脉

  1. 登录线上服务器后发现tomcat实例并没有死掉,依然还存在,cpu、内存耗费的也不大,80端口依然被占用,通过浏览器输入http://localhost 不响应,但telnet localhost 80会返回信息。
  2. 试图去寻找相关日志,tomcat_home/logs下没有任何日志,试图使用jvisualvm查看tomcat内存和线程状况,但在jdk目录下却找不到这个工具。试图使用jps和jstat工具,但不能发现java进程id。
  3. 猜测是内存配置太小或者线程死锁问题,但没有证据支持。试图修改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 
  4. 百思不得其解,仔细观察系统的部署方式,发现和官方推荐的方法不同,是通过自己写的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采用序列化方式。
  5. 通过初步配置大内存,系统稳定了许多,但是司机现象依然存在,只是出现的频率小了,怀疑有数据库慢查询,通过开启数据库的慢查询日志,发现大量慢查询语句,这些语1句基本都处理影片屏蔽功能的,需要解决这些慢查询。
  6. 分析这些慢查询语句,发现有两个问题:
    1. select处理过多的字段,特别是影片简介字段,很长但在页面显示时却并不这些数据,占很多内存空间,这样可能造成年轻代gc频繁,当用户量大时,年轻代频繁gc造成老领代暴增,最终造成full gc,但大量页面请求还没有完成,内存数据依然在不能被gc,所以频繁full gc。
    2. 频繁select,多个方法其实使用大致相同的数据,完全可以一次读取所有数据,在多个方法中传递使用,降低select和数据对象构造的频率,从而降低gc频率。

[编辑]深度研究

  1. 为了彻底解决这个问题,特地部署测试机,采用jdk64位最新版+tomcat6 64位版本,采用官方推荐模式部署,然后通过loadrunner做压力测试
    1. 首次测试,并发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内存配置
    2. 再次压测,50人10分钟即崩溃,分析gc日志,年轻代的gc频繁,老龄代上涨迅速,有一段时间持续full gc,每次都不能释放内存,持续full gc造成程序不响应,猜测内存泄漏,查找代码视图发现有泄漏的静态变量,但未发现泄漏点,通过jstat分析tomcat进程内存,发现1小时内不再访问系统,内存会逐渐降下来,所以分析,没有内存泄漏点,是gc频率造成。
    3. 慢查询解决后压测,本次测试使用50并发,压测1小时,系统响应响应,但会出现数据库连接失败异常。分析应该系统访问数据库没有使用连接池,而是直接使用jdbc连接造成的。
    4. 到此为止,需要解决的问题就只剩下数据库连接池问题了。试图使用jndi来实现连接池:
      1. 乱码问题,曾经试图使用过jndi连接池,但发现数据乱码,不能解决,一般google的结果是在数据库url中增加characterEncoding=utf-8即可解决,如果有问题,把'&'修改为'&',即可,但我们的却不行,分析发现系统使用的jdbc驱动是3.x.x版本,但数据库是5.0版本,猜测是jdbc驱动不匹配,换成5.0.8解决乱码问题。
      2. 日期型数据问题,乱码问题解决后,发了日期型数据处理有问题,当数据库datetime字段为0时,系统报不能把'0000-00-00 00:00:00'转化为datetime异常,但在jdbc3.x.x下没有问题,应该是换jdbc驱动造成的,经过google发现,在url上增加zeroDateTimeBehavior=convertToNull即可解决。
    5. 再次压力测试还没有开始,5月14号后需要再次测试。

[编辑]反思

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

[编辑]其他

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

  • 删除webapps下原来的所有应用
  • 删除conf/catalina下所有
  • server.xml中Host元素下添加
    <Context>path="" docBase="/WebApp" reloadable="true" crossContext="true" </Context>
### 三级标题:服务器频繁宕机的排查方法 服务器频繁宕机是一个复杂的问题,涉及多个层面的排查。以下是系统性的排查方法: 1. **检查日志文件**是排查服务器宕机的第一步。通过分析日志文件,可以找到宕机发生时的异常信息,例如内存不足、CPU使用率过高等[^1]。 2. **监控系统资源**,包括CPU、内存、磁盘I/O和网络带宽。在宕机发生前,观察这些资源的使用情况,判断是否存在资源耗尽的情况[^3]。 3. **检查应用程序的健康状态**,包括是否有循环、多线程造成的锁现象,以及消耗系统资源的逻辑导致资源耗尽等问题。 4. **检查服务器硬件和系统配置**,包括服务器硬件故障、服务器配置过低、系统参数配置不合理、系统内核bug等[^3]。 5. **检查人为因素**,如误操作导致的服务器宕机。 ### 三级标题:服务器频繁宕机的原因分析 服务器频繁宕机的原因可以分为以下几类: 1. **服务器硬件故障**,例如内存故障或硬盘损坏,需要更换或升级硬件[^3]。 2. **服务器配置过低**,导致即便访问量不算太高也超出了系统承载能力,需要提高配置[^3]。 3. **应用程序本身存在bug**,例如循环、消耗系统资源的逻辑导致资源耗尽[^3]。 4. **多线程造成的锁现象**,互相等待对方释放资源[^3]。 5. **人为误操作**,例如错误的配置更改或不当的操作导致的服务器宕机。 ### 三级标题:服务器频繁宕机的解决方案 针对服务器频繁宕机的问题,可以采取以下解决方案: 1. **优化应用程序**,修复应用程序中的bug,例如循环、多线程造成的锁现象,以及消耗系统资源的逻辑导致资源耗尽等问题[^3]。 2. **升级服务器硬件**,提高服务器的配置,以满足更高的系统承载能力[^3]。 3. **调整系统参数配置**,例如提高文件描述符(fd)个数或允许连接数等。 4. **升级系统内核**,解决系统内核中的bug,例如软锁等问题。 5. **定期维护和监控服务器**,及时发现潜在问题并采取预防措施,提高服务器的可靠性[^4]。 6. **实施负载均衡**,分散服务器的压力,避免单点故障导致的服务器宕机[^4]。 ### 三级标题:代码示例 以下是一个简单的Java代码示例,用于监控服务器的CPU使用率: ```java import java.lang.management.ManagementFactory; import com.sun.management.OperatingSystemMXBean; public class CPUMonitor { public static void main(String[] args) { OperatingSystemMXBean osBean = ManagementFactory.getPlatformMXBean(OperatingSystemMXBean.class); double cpuLoad = osBean.getCpuLoad(); System.out.println("Current CPU Load: " + cpuLoad); } } ``` 此代码使用Java的ManagementFactory来获取操作系统的MXBean,并通过getCpuLoad方法获取当前的CPU负载。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值