软件开发
APP开发公司
手机软件
苹果IOS开发
android安卓开发
会员系统
三级分销
网站建设
商城网站
小程序开发
微信公众号开发
联系电话:18842388900

关于某项目系统稳定性调优解决方案

一、 系统问题:

系统频繁发生不稳定现象。

二、 主要原因:

1、 主要问题是数据库连接经常中断。
2、 web线程不足造成内存溢出现象。

三、 解决情况:

现已解决系统频繁发生不稳定现象,后继仍要再对该情况进行跟踪观察。

四、 解决方法:

1、 主要问题是数据库连接经常中断。
1)平台对于数据库连接池的管理存在bug,对于idle的连接,没有启用回收线程定时清理,导致回收池的线程越积越多
2)修复公司平台的回收线程bug,并在初始化缓冲池时启用。
3)不断产生僵死事务(不提交,无超时)。
4)在程序中增加事务提交的处理。
2、 web线程不足造成内存溢出现象。
1) 设置web线程最大并发数为300个,允许大概50个用户并发。
2) 将JDK的初始化内存调整到1500M,决定内存溢出现象。

五、 具体解决细节:一、 应用程序部分问题解决情况

1. 数据库连接无法获取
 原因:
1)平台对于数据库连接池的管理存在bug,对于idle的连接,没有启用回收线程定时清理,导致回收池的线程越积越多。
MinervaConnectionFactory.java中初始化数据库缓冲池的地方,只从配置文件读取了线程池的最大和最小设置,没有启用回收线程。
 
ObjectPool.java中的第858行逻辑判断有误,表示当前线程有用户正在使用并且闲置时间过长则回收。
 
2)不断产生僵死事务(不提交,无超时),回收池中的此类进程越来越多。跟踪事务的执行语句,定位出程序中相应的代码块,调试发现程序员手工开启的事务没有提交。

GenericEvent.java和ReportEvent.java中的导出报表方法,存在手工开启事务但从不提交的代码。dbUtil.getConnection从连接池取得一个连接,在preStm.executeQuery()处开启数据库事务,最后直接用rs.close()和preStm.close()把连接还给连接池(注意此处并不能关闭连接),没有任何提交事务的处理,所以从数据库后台管理可以查看这个线程一直持有事务。
GenericEvent.java: 
ReportEvent.java:
 

解决办法:

1) 修复公司平台的回收线程bug,并在初始化缓冲池时启用。
MinervaConnectionFactory.java中初始化数据库缓冲池的地方增加闲置进程可回收和启用回收线程的设置。
 
ObjectPool.java中对回收的逻辑判断进行修正,如果当前线程未被使用并且闲置时间超过设置时,则进行释放。注意,连接池始终会保持连接数不小于初始化时设置的最小数。
 
2) 在程序中增加事务提交的处理。
在GenericEvent.java和ReportEvent.java中增加事务提交处理,语句执行完后进行提交,如果出现异常则回滚,最后归还连接给连接池。
 
2. web线程不足

原因:生产环境之前设置的web线程最大并发数是100个,一个并发用户大概增加5-6个线程处理,当超过16个左右用户并发登陆时,将报错。

 解决办法:设置web线程最大并发数为300个,允许大概50个用户并发。在生产环境中查了半年以来在线用户的情况,基本上每天总的登陆账号数在100个以下。
按照系统一天使用8个小时(T),每天平均100个用户访问(n),每个用户平均访问时间为1小时(L),平均并发用户数(C)为:
C=nL/T=100*(1/8) = 12.5
峰值并发用户数(C^)约为:
C^ C+3*  12.5+3*3.5 23
按照平均并发12.5,峰值23,目前设置的web线程最大并发设置已可满足。如业务量有上升,可根据以上公式推导,在配置文件中调整最大值:
ofbiz-containers.xml:
 
3. 内存溢出
12月21日对JDK的初始化内存调整到1500M后,至今未再出现。

二、 数据库部分问题解软件开发决情况

1. 发现存在大量的本地连接,从重启数据库服务后到现在一直没有关闭连接,通过查询当前活动事务,发现大量处于活动状态的读写类型事务,通过跟踪发现是应用程序问题,已修改应用程序解决。
 
2. 数据库配置在64位系统时不需要开启AWE选项,目前已关闭。
 
3. 数据库备份计划从11月份开始就一直处于失败状态,付海涛正在制定备份计划故障的解决方案。

三、 后续工作

1、 持续跟进数据库连接池情况
请项目组通过sql server的活动监视器监控生产环境后台进程数量,一般情况下,web应用占用的进程数是80个,加上后台扫描服务和短信服务,总数在90~100个;打开事务的进程数量基本趋于0。
 
2、 优化手工开启事务的程序
通过这两天的观察和分析,绝大部分锁死事务的所执行的SQL都是由GenericEvent和ReportEvent产生的,目前这两个文件我已经修正。但是通过在工程里全量搜索手工开启事务(包含PreparedStatement)的代码,仍然大量存在,约涉及到90个类文件,其中部分有提交处理,部分没有提交处理,而是直接还回线程池。
鉴于涉及面太广,建议项目组采用被动的方式优化。即通过监控数据库后台,记录僵死事务对应的SQL,再定位程序代码进行修改。
3、 制定数据库备份计划解决方案
将针对数据库备份计划

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。