性能优化心得

系统的性能的好坏由很多因素决定,我从实际项目经验中总结大概有如下几点:

1sqlhql查询语句编写的好坏

2代码中递归,循环嵌套未正确使用

3数据库及连接池设置未进行优化

4tomcat设置未进行优化

5框架的性能制约 如struts2

关于sql语句和代码引起的性能问题,本篇暂且不谈。这里仅谈谈如何优化系统运行的环境,来提高系统的性能。

    从我某个项目情况来看,服务器的配置都算还可以的,所以我们在给服务器安装装操作系统时一定要用64位的系统(server 2003server2008),oracle10.2g 64jdk1.6/1.7 64,tomcat6 64位(暂不推荐使用tomcat7,因为有些工具暂不支持tomcat7)。

为什么使用64位大家应该都懂得,32位的系统和软件支持的最大运行内存4g以下,而现在的服务器内存动辄16g32gcpu n核,剩余的内存和cpu不利用太可惜了。而大内存和多cpu意味着更多的缓存和并发。

下面以某项目为例

在测试组配合下对部署好后的项目使用loadrunner11进行系统登录并发测试(2003server 64tomcat6 32oracle64jdk1.6 32位)

2003server 64位注意打上sp2补丁

Oracle64位 安装时注意调整进程大小 在安装第10步,选择调整大小标签,默认150,设置为1500(根据服务器硬件配置来定,比如本服务器内存为32g性能较好,低一点的设为1000

系统登录看似简单,实际上是一个比较复杂的过程:

1验证用户

2初始化用户 模块 角色 权限等

3记录登陆日志

4跳转首页(首页显示时又会带来很多ajax请求,数据库查询和后台数据处理)

因此测试用户登陆系统的业务场景能够很好的反映系统的性能。闲话少数,进入测试。

lr加载100用户,同时并发登陆系统,结果系统立刻崩溃,系统后台显示连接池超过最大连接,这个简单,直接修改applicationContext.xml中相关连接池设置

因为oracle已经设置最大连接为1500,所以这里可以放心的调大一些

  1. <!--初始化连接数-->
  2. <property name="prototypeCount">
  3. <value>200</value>
  4. </property>
  5. <!--连接池最大连接数,比oracle最大进程数稍微小一些-->
  6. <property name="maximumConnectionCount">
  7. <value>1200</value>
  8. </property>
  9. <!--最小连接数-->
  10. <property name="minimumConnectionCount">
  11. <value>50</value>
  12. </property>
  13. <!--这个值和并发有较大关系,可以设置大一点否则在高并发下可能会报这个错误We are already in the process of making 6 connections and the number of simultaneous builds has been throttled to 5-->
  14. <property name="simultaneousBuildThrottle">
  15. <value>100</value>
  16. </property>
复制代码


以上的值是经过几次测试后定下来的。可以通过,但不一定是最合理的配置

做好这些设置重启项目再继续测试,100用户顺利跑过,系统未报错,并发测试通过。

    再测系统的负载能力,就是在高并发下,系统的持续运行能力,反映这个能力的一项重要指标就是系统事件(完成登录全部过程)平均响应时间,测试完后发现系统响应时间较高在30秒以上,这就是说,当100用户在同时登录时,后面的如果还有人再登陆就得等待30秒以上,这个速度可能是大家接受不了的,所以要进行优化。

    首先还是考虑是不是数据库的问题,在开发框架里的系统设置里面有个工具是来查看proxool的连接数及执行情况的,这个工具有一个重要的功能就是会记录数据库sql操作的持续时间,打开一看果然有好几处的sql操作时间鲜红超过5秒以上的(正常通常是几十ms),点开一看找到sql语句,是登陆后首页查询语句较多,这些语句都是用jdbctemplate进行查询的,所以可能要对spring里配置的jdbcTemplate优化一下

applicationContext.xml

  1. <!-- spring jdbcTemplate 配置 -->
  2. <beanid="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
  3. <property name="dataSource" ref="dataSource" />
  4. </bean>
复制代码

所以我想到可能得对jdbctemplate进行设置,直接找到

org.springframework.jdbc.core.JdbcTemplate查看代码,发现这个类里面有几个属性,一看就懂,所以修改后配置如下

  1. <!-- spring jdbcTemplate 配置 -->
  2. <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
  3. <property name="dataSource" ref="dataSource" />

  4. <!--fetchSize 一次抓取结果大小-->
  5. <property name="fetchSize" value="50" />

  6. </bean>
复制代码

这个设置完以后,再对首页后台的几处sql进行优化后再次负载测试,查看proxoolsql执行持续时间,全部变为绿色。此时平均响应时间有所降低,但还是比较高,可以肯定不是数据库的原因,具体是什么原因暂且不说,因为当时我也不知道是什么情况。暂且搁下负载,继续并发测试,刚才是100用户,现在加到200用户,一跑,tomcat报错,说tomcat连接达到最大值,这个我有印象

找到tomcat/conf/server.xml 修改

  1. <Connector
  2. URIEncoding="UTF8"
  3. connectionTimeout="20000"
  4. acceptCount="2000"
  5. maxSpareThreads="500"
  6. maxThreads="1500"
  7. minSpareThreads="100"
  8. port="8080"
  9. protocol="HTTP/1.1"
  10. redirectPort="8443"
  11. useBodyEncodingForURI="true"/>
复制代码

改完以后再进行200人测试,tomcat直接报内存溢出:java.lang.OutOfMemoryError: Java heap space

关于tomcat内存溢出及启动内存设置的问题,大家可能在网上能搜到很多结果,

大多给的解决办法就是 在catalina.bat中加入下面的设置

  1. set JAVA_OPTS=-server -Xms512m -Xmx1024m -XX: PermSize=128M -XX:MaxPermSize=256m
复制代码

注意:-XX: PermSize=128M -XX:MaxPermSize=256m这两个值很重要,在ssh项目中由于spring会生成很多代理类,如果这个值不够大的话,会导致项目在tomcat启动时就报java.lang.OutOfMemoryError: PermGen space


调整完以后,继续200人测试,仍然是内存溢出,将-Xmx1024m再调大一些,发现tomcat直接不能启动,到此我猜想tomcat32位的最大内存也就止步于此了,得换64tomcat6,一人得道鸡犬升天,jdk也换64位,一狠心直接升级到jdk1.7 64

升级完以后,加大-Xmx2048mtomcat顺利启动,但是有几个警告(connector ssl中的几个参数不对),暂时忽略。用lr200人继续测试,没有内存溢出,但是tomcat又报超过最大200线程的错了,刚才明明已经设置了maxThreads="1500",为何还报这个错呢,注意到刚才tomcat启动的警告,就是说这几个参数不对,并且ssl设置的pki登陆也不能用了,估计是tomcat升级到64位后的问题,查了半天发现tomcat 64位中server.xml配置中的几处协议需要改下

Server.xml 以下两处需要修改

1<Connector port="88" protocol="org.apache.coyote.http11.Http11Protocol" connectionTimeout="20000" ../>

2<Connector port="8443"
protocol="org.apache.coyote.http11.Http11Protocol" SSLEnabled="true" ...../>


修改后重启tomcat继续压力测试,200人全部通过,250人全部通过,但是系统平均响应时间仍然较长20-30秒。检查数据库没什么问题,tomcat也升级了,那怎么还慢呢,系统也没报错,怎么办?

继续查资料,发现一款神器:Jprofiler7一款能够检测java项目性能的工具,和lr不同,lr能测出性能不好,但不知道是哪里的出的原因,而jprofiler可以告诉你是哪里卡住了,里面有一项重要的指标就是Threadbolcked Time(阻塞时间)。

    直接在jprofiler里跑tomcat,同时运行lr200负载测试,发现所有的线程阻塞都指向了同一个类(Struts2中的一个类),以前一直传说struts2的性能有问题,看来这回出现了,百度,没有资料,google天朝屏蔽。最后直接上struts2项目的jira,搜索bug,居然真搜到了,显然官方承认,在版本2.2.x中存在这个问题,说在2.3.1中解决了这个问题。于是升级struts2,直接升级到最新版本2.3.8,换了系列struts2 jar包后,启动项目各种报错(你懂得),一一解决,比较棘手的一个问题就是,struts2.3.8和我们开发工具jrebel有冲突(不知道最新版的有没有这个问题),这也是偶然发现的,一开始升级sturts2后在myeclipse里跑怎么也启动不了,以为是jar包冲突,后来发现直接跑tomcat就可以,我就怀疑是jrebel的问题,去掉jrebel果然可以了,但是去掉了亲爱的jrebel怎么行呢,他节约了我们程序猿们多少宝贵的时间……(何止事半功倍),直接研究下jrebel jar包,用winrar打开jar包,在plugin目录下有struts2-jr-plugin-5.0.0.jar 和struts2-jr-plugin-5.0.0.jar.sig两个文件,猜测可能是这两个包不匹配最新的struts2,于是直接从jar包中将两个文件删掉,myeclipse继续加载jrebel,项目正常启动,修改类后热部署正常。(有没有其他影响暂时不得而知,改天去查下jrebel最新版)至此升级完毕。

继续用lr+jprofiler测试,发现刚才阻塞在秒级以上的线程不复存在,各个线程都在平缓的变换着,阻塞时间变为毫秒级。最后测试在200人的压力测试下,系统平均响应时间在5秒左右,250人在9秒。想进一步优化,发现阻塞时间仍有一部分是在struts2上,这些阻塞没什么太大异常,可能struts2的性能确实只有这样了。

      在性能优化上光依靠64位系统带来的大内存和多核是不够的,网上说采用32tomcat集群的部署方式大于单个64tomcat6扩展大内存的部署方式,由此我得出,真正的系统性能提高不是靠优化一台服务器,一个tomcat能搞定的,而是需要采用服务器+tomcat集群的方式来部署系统,也即负载均衡。关于集群和负载均衡不在本篇讨论。

以上是本人在项目性能优化中的一些心得体会,难免有表达不妥和错误遗漏之处,请大家不吝指出!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值