项目性能优化经验--ZY项目

最近负责给公司某个ZY项目进行性能优化的一些经验分析

碰到问题:

1. 压力测试到100并发,任何一个场景CPU暴高,接近100%

查询jstack日志,发现大部分的线程block在tomcat 的 http11.connect 的poll方法上 或者是c3p0连接池的获取上

同时发现该项目数据库连接池配置了2000+,仍然不够用,100并发

分析原因: 数据库连接有问题

打开hibernate日志,关于transcation的

<logger name="org.hibernate.transaction" level="DEBUG"/>

<logger name="org.hibernate.cache" level="DEBUG"/>

<logger name="org.hibernate.type" level="DEBUG"/>

在logback.xml 中配置

然后本地运行代码,发现成百的下面日志

DEBUG org.hibernate.transaction.JDBCTransaction - begin

DEBUG org.hibernate.transaction.JDBCTransaction - current autocommit status: true

DEBUG org.hibernate.transaction.JDBCTransaction - disabling autocommit

DEBUG org.hibernate.transaction.JDBCTransaction - commit

这里显而易见出了问题,整个流程中怎么可能打开和关闭如此多的事务,要知道每次commit的时候都会去数据库连接池申请并释放连接,不要说2000,加个0都不够用

仔细查看代码,在整个系统DaoImpl的Base类上,被加了@Transcational 注释,同时几乎大部分的方法加了次注释

要知道,spring看到这个注释就会打开事物的,方法结束关闭事物

所以首先要做的就是,去掉多余的事物

将显而易见的事物去掉之后,系统性能显著提高,至少压倒500并发,CPU也只有在60-70%

2. 数据库连接依旧不够用

经过上面的调优,发现数据库连接池依旧不够用, 500并发以上,出现大量BLOCK 线程在等待数据库连接资源

需要继续调休代码

继续review日志

发现仍旧很多事物操作,特别是空事物操作(即打开关闭之间什么数据库操作都没有)

发现系统db操作框架仍旧有问题:

举例一:

@Transcational

public void delete(String ids...)

{

    if( ids != null){

      for(String id : ids){

        delete(id);

      }

   }

}

这个方法有两个严重的问题:

1. 如果ids 为空 那么就会有一个空事物操作

2. 循环的一个个delete

第一个问题,可以通过提供一个统一的入口来判断,然后非空在进入到事物操作中

第二个问题,代码框架的不完整性,作为一个合适的base框架至少要对于delete要提供一套根据ID删,根据ID组删(用delete in list(ids)), delete 对象方法等,而不是简单的一个delete方法,任何其他delete都使用这个

再次清掉很多空数据库连接之后,系统数据库连接仍旧不够用

3. 继续找问题

轮到业务逻辑调整:

1. 连接数太多的问题

因为系统采用了 freemarker的框架, 在ftl的模板中涉及到了header和footer

这两个模板文件中,加入了对用户信息的查询请求,导致这个流程中对于/member/info.jhtml的调用多次出现,同时还有其他很多的请求,一个产品列表的页面,会导致8次jthml的连接请求,整个测试流程更是多达几十次的连接

所以,需要优化连接数量,减少连接,对于重复不必要的连接,将信息缓存在session中, 对于一些连接尽量能合并的合并

减少连接,能够连接建立和释放连接的开销(提高整体响应速度)

2. 查询太多

整个流程中,光是涉及到产品的查询及其级联查询多达5,6百条,不可忍受,绝对需要缓存,必须缓存

这样既可以提高每个线程db连接使用的时间,间接就提高了连接池连接释放的概率,降低了连接等待的可能

经过以上的代码调优,目前整个系统已经达到客户要求

整个系统代码框架为

html5(jquery) ----------freemarker ---------spring MVC  --------memcached --------- hibernate  ---------MYSQL

然后系统搭建

最外层 使用 nagix (主备) 转发请求 

后台 tomcat 6 个集群

使用 mysql 中间件 Amoeba

mysql 做 读写分离 + 主备 (2 台 读 , 2台写)

相关推荐