网店版重生项目中,因为我们要将最主要的核心数据由Oracle迁移到分布式Mysql中;虽然说业务逻辑不进行任何改动,只是将数据源由单一的Oracle改造成基于Mysql的动态数据源,但为了保险起见,我们还是要求做一次性能测试,但怎么圧呢?这个系统已经2年没有比较大的系统变动了,但是用以前的性能测试结果来和新系统做对比,大家都觉得不那么匹配,所以我们决定:对现有的老系统的关键模块重新进行一次压力测试,然后和新系统相同模块的压力测试结果进行对比,看新系统是否有明显的性能下降!
但对老系统进行压力测试的结果却令我们大失所望,远远超出了我们的想象,一些并不复杂的功能点都只有不到20的TPS!这下可把我们吓坏了,依据我们原有的性能测试数据,类似的功能模块一般都能达到100TPS左右,难道系统真的年老失修已经变成了现在这么慢的地步?我们自己当然不相信,因为系统并没有进行过大的架构调整,于是开始了路漫漫的排查过程;
性能测试过程中反映出来的现象为:不管多少并发用户访问、系统的TPS都只能保持在十几,但是Web服务器、DB的压力却很低,增加并发数也没有用,而且每个请求的响应时间并没有下降,整个应用的TPS曲线非常稳定,长时间压力、增加并发用户等也都没有下降的趋势!
- 首先,因为Web应用服务器和DB的load都很低,而且新增并发用户压力也都没有增加的迹象;
所以我们怀疑是否压力真正到了Web服务器上,是不是压力测试脚本有问题,于是我们利用现有测试脚本,只是随便换了一个只通过apache访问的静态资源,压过之后发现没有问题,TPS立马上去了,能够达到几千; - 在确认了apache没有问题之后,我们怀疑是否apache、jboss之间的桥接出了问题?
我们默认采用的是weblogic的apache转接module,检查相关配置项之后也没有发现任何问题,只是开启了一些日志项,有时候日志打印也会导致性能瓶颈,关闭之后再圧,仍然没有起色;
我们也考虑过换一个桥接器,比如用mod_jk,但由于我们几乎所有系统都是采用现在weblogic的module,且都没有问题,所以我们决定暂时不做这个调整测试; - 为了彻底验证是否因为apache、jboss之间的桥接出现了瓶颈,我们干脆把apache去掉了,直接访问jboss;
再次压力的测试结果仍然是一样的,没有任何变化; - 从我们通过Interceptor打印出来的服务端页面所消耗的时间来看,页面的响应速度和我们预期是差不多的,而且增加并发用户并没有导致响应时间下降,所以我们还是要想方设法来解决掉这个问题,至少要让web服务器的压力上去、或者让页面的响应时间下降!
此时我们换了一个更简单的、没有数据库访问的Jsp页面进行压力测试,测试结果令我们出乎意料,TPS很快能够达到好几百; - 在对纯粹jsp页面测试的结果之上,我们怀疑是否是因为各类Interceptor、Filter所消耗的时间太长或者出现瓶颈,因为通过我们的interceptor打印出来的消耗时间是不包括很多拦截器的;
于是将很多的拦截器去掉之后再圧,结果却还是和前面一样,TPS无法获得提升; - 此时我们怀疑是否因为Tomcat默认配置的250个线程数太少?但这明显说不通,因为我们的测试脚本按理论计算都没法达到每秒250的请求量;但我们还是通过jmx-console中的stat查看了当前jboss接收的请求数情况;
从console stat的结果来看,感觉还是有些不对,因为偶尔真的会出现阻塞,250个线程并用完了,还有一些正在等待,这和我们理论计算的结果是相冲突的,于是问题还是回归到了应用本身,应用的确有问题; - 前面我们一直坚信,应用是没有问题的,应该是测试环境、或者压力脚本、或者其他什么导致了这个性能瓶颈;也就没有真正从应用这个角度来分析;
关键时刻,看来还得要用终极命令kill -3来查看jboss当前情况下dump出来的堆栈信息了,马上行动,果然有发现!先看看我们dump出来的一些关键信息:
从上面看出,很多的线程都被lock住了,而且都是在ConfigurationManager.conditionalReload;
Wow,一下子恍然大悟喽,这是webwork的一个配置项导致的结果,就是在开发阶段为了方便,系统会每次都去检测xwork.xml文件是否有修改过,如果有修改过就重新加载,这个配置项就是webwork.configuration.xml.reload=true;
将配置项设置为false之后再圧,果然问题就出在这儿,一切正常,TPS恢复到90多,问题搞定!
从这次的性能测试瓶颈问题解决历程可以看出,环境配置有多么的重要,往往一个debug级别的参数设置会让整个应用的性能下降好几倍!另外,就是对命令kill -3的使用,一般还可以结合jstack一起使用,但一般来说前者dump出来的信息会更全一些,但该命令也不一定使用一次就能发现应用的所有问题,有时候可能需要多次使用,然后一起分析dump日志;