2012-12-18日
下午开会探讨北京项目出现的一些问题,当时记录的问题是由可能因为有一定数量的客户上来后,就造成了Web服务器宕机,而且没有任何时间上的规律性,让我准备出差到北京,限定三天时间,以及准备测试压力的工具软件等等。
2012-12-19日
上午飞抵北京后,进行了安顿安排,以及开会听王经理讲了一下情况。由于服务器已经在生产网上,客户在使用,北京大概有100多个将近200个收费网点,每天都有很多客户在排队缴费,所以不能进行相关的压力测试,只能在晚上进行。下午针对简单的操作编写了压力测试用的操作逻辑。
晚上和大家一起进行做对系统的初步压力检测。
检测结果:
本机搭建的Web服务器和一台数据库Oracle服务器并发1000人的登陆的结果是,虽然内存有逐步的上涨,但没有宕机。
真对运行生产网进行了压力测试检验后,和白天也出现的宕机状态一样,初步分析应该不是因为程序的架构缺陷,以及程序的编写缺陷造成的原因。
2012-12-20日
针对系统现象表明,如果在集群内,一台服务器宕机,另外一台服务器不在集群入口进入的话,还可以使用。但如果有新登陆的客户,如果被分载到了宕机节点后,就会登陆不进去。晚上测试的现象表明,如果宕机了,Tomcat还没有挂掉,而在登陆的时候连接不上数据库,并且根本没有连接数据库失败的报错。但如果把数据库服务器网线拔掉后,就会在页面进行报错,当时分析有可能是数据库连接池的原因,但把数据库连接池设置很小后,也会在页面上提示连接失败,并不会宕机。此时分析的结果,有可能是在连接发送到Oracle数据库后,没有返回造成的。随即又做了个压力测试,把Oracle服务器进行全面的性能压力堵塞,在用Web服务器进行连接,这个时候很慢,页面反应效果很像,点连不进去。不过Oracle的CPU和内存利用几乎是百分之百,局域网内部人去连接Oracle服务器几乎没反应了。和白天的症状不一样,白天一台web服务器宕机后,另外一台服务器还可以很顺利的进行与Oracle服务器进行交互,而且其他用户还可以利用PL/SQP查看系统有没有死锁等症状。由此判断不是数据库的原因。
2012-12-21日
由于针对前段症状的分析,程序上没问题的话,怀疑可能是Tomcat服务器造成的原因。Tomcat导致宕机的最大可能性就是内存及缓存的溢出造成的。于是把JVM的内存和最大最小内存连接池以及线程池都设置到最低,然后Web服务器运行后开始进行压力测试。虽然效果和昨天的页面反应情况很像,从测试机器的Logs里可以查出(严重: Caught exception (java.lang.OutOfMemoryError: Java heap space)即内存溢出),但是,我又查看了一下服务器的相关记录,并未找到任何一条关于内存溢出的错误日志。通过核对客户群里对系统反应错误的时间,以及核对集群Apache和两个Tomcat出错日志的比对,看看是否能够和集群的相关配置有关。
从日志的结果分析来看,apache在宕机时间内,有两次显示” [Thu Nov 15 14:13:05 2012] [warn] Server ran out of threads to serve requests. Consider raising the ThreadsPerChild setting”,这个意思是表明apache作为控制器来讲,他的允许线程数已经不够用了,后来看了一下Apache配置” conf/httpd.conf”文件,发现ThreadsPerChild默认为250。后来查询了相关资料,这个线程一般为最大可以为1920,然后我就把它调节到了1000。由此分析,本系统的应用负载,是现在的架构节点远远不够的。但从数据库的日志,以及tomcat相关日志,并没有对数据库出现异常的相关信息,比如连接速度慢,查看了linux下oracle的日志,也并没有线程以及内存相关的溢出信息,由此分析,瓶颈并不在oracle。于是为了验证想法,又增加了两个负载节点,观察服务器的动向。
2012-12-22日
由于工作已经超出原定的三天,也就既来之则安之。而且经理说了,周六周日的人,并不多,每天上来缴费的网点差不多50,到60人左右,想最好是先观察一下。不过今天是周六,一整天都平安无事。
2012-12-23日
为了安全起见,我对各种引起宕机可能的情况作了总结。一、内存溢出,二、表死锁,三、数据库连接池死链接,四、数据库瓶颈压力过大,五、负载均衡器入口瓶颈压力过大。当日查看了tomcat的系统日志,发现session会话复制失败率很高。因为两个或多个web服务器做负载的时候,为了保证高可用,要在一台服务器宕机后,自动切换到另外一台服务器。但我们的系统有个问题,因为是采用extjs作为前端,ajax与后台操作量非常大,从而导致服务器session复制两就很大。
由Tomcat的系统管理页面可以看出,http协议与外面交互,这一上午的吞吐量也不过52MB,而用于session复制的ajp协议,却达到了133MB。为了认证这一说法,我把其中一台节点服务器的session复制关掉,为了迎接明天压力的到来。
2012-12-24日
今天上午的时候,反应还良好,只不过其中有一台服务器稍微有些慢。不过到下午15:24的时候,从负载机,带集群节点,统一宕机。当然其中也包括我那台被关闭session复制的服务器,当时我就蒙圈了。我觉得不可能,没有任何理由啊。因为从负载机进去,就一个IP地址,但各个集群机都有各自的IP或端口,即使是一两个节点宕机,乃至三个节点宕机,但其中那台没session复制的机器也不应该啊。难道是Oracle有防火墙,同一时间出现网络闪断,但那也不用非得重启web服务器才好用啊,因为重启一个节点时,那个节点就好用了,不过另外的节点还是不好用。晚上的时候,开始在Linux查找各种问题。连接,以及日志,结果还是没问题。
2012-12-25日
没办法了,只能出最后绝招了。因为系统宕机原因跑不出那五个原因,我决心全面监视起来,每一个信息参数都记录日志,然后进行分析。于是,我就做了个程序,监视内存,JVM内存,JVM的CPU,死锁的表,用户操作登陆及日志,连接池,以及web服务器和数据库服务器的TCPIP流的吞吐量。剩下就是漫长的等待了,果然在下午两点多,Tomcat的JVM空闲内存值,一个节点在一小时内急速下降到0,然后JVM内存溢出,紧接着表开始死锁,然系统页面开始反应缓慢。
通过以上的现象来看。一天的操作都很正常,空闲内存突然的下降。引起了我很大的怀疑,同时我查看了那个时刻的Http页面的吞吐量。也是50多兆。不过JVM内存我可设置了1.5G,完全不是一个数量级别。就并发干整它一个星期,也宕机不了。一定是程序逻辑有问题,造成了内存超大的累加。
没办法,只能看是什么操作了,于是我划定了宕机时间段儿,通过群里的聊天记录,找出宕机的时间范围,然后把这几天的宕机时间内所有的操作日志调了出来,然后找出它们共同的操作。这个时候,“税控机导入”,这个日志这个词,紧排在“登陆/退出”的后面,立刻引起了我的注意。紧接着我就询问了开发人员,然后再我机器上搭了一套模拟环境,开始对这个操作日志进行了压力测试。结果表明,连续上传了三次,系统就JVM内存不够了,而且表被锁住。因为如果传一个比较大的excel,会出现上传时间很长的状态,如果没有耐心烦,就会把页面关闭,虽然关闭,数据库连接池并没有释放。紧接着使用者就会再次登陆,在去实验上传,然后屡试不爽。当他在实验的过程中,线程池,连接池一个个的被占满,内存逐渐溢出。其他人使用,不但反应缓慢,而且登陆都登陆不上去(因为连接池被占有没有释放)。
就此为止,罪魁祸首就浮出了水面。
就此处问题,我提出了解决方案。因为系统硬件为16个G的内存,不过32位电脑JVM最大只支持到2G,而且excel上传并不耗费很大资源,只不过系统在读excel往数据库里插的时候,会耗费很大的内存空间。本来tomcat就最大1.5G的支持,几下就死掉。所以,只能把处理excel插数据库的任务,交给另外的进程和线程去做。做个服务,或应用啥的。实时改造的方法,可以利用消息队列进行业务接受。当上传成功后,就在消息队列内进行排序。然后服务读取到消息后,进行处理,等成功后在回执。
2012-12-26日
准备收工,改造方案的落实。