系统性能调优

最近工作一直在忙与改善系统性能,做压力测试,期间学习了下Jmeter做了简单的压力测试,总结一下最近的工作经验。
首先简单介绍一下系统的结构,我们公司是做业务系统,采用的数据库是MySQL,应用服务器是Jboss,其中用到了EJB 包或stateless、stateful session bean,前端只使用了Servlet,因为页面相当简单,只有几步http操作,但是并发量会很高,所以要求处理业务尽量的快,首次调优目标是1×Jboss + 1×MySQL并发500,Jboss与MySQL各自都是独立的物理服务器,双核3.0G + 4G内存, 目标每个业务平均响应时间不超过3s,.

我最近的工作主要从三方面入手,因为系统是第一次做调优,考虑的地放可能还不够欢迎大家提出建议.

1.DB

首先呢,应该从数据库索引入手,对于程序中经常用到的查询字段而非主键或、外键或者唯一约束字段 应该建立索引,但又频繁查询又频繁更新的字段,就要慎重考虑,查询时间是可以大大缩短,但数据库维护索引的时间大大增加,搞不好变成了拆东墙补西墙.
这部操作会很大幅度提高系统性能.
其次,需要增加最大连接数,我们用的MySQL5,默认的最大并发连接数是150,暂时我调整到1000.如果这里不改变,那么你的Jboss连接池再大也没用.
还有一点需要说一下,mysql默认的6小时内连接没有通信,就会kill掉这个连接,要么在这里调整mysql的最大连接空闲时间,要么就去Jboss那边设置一下每隔一段时间检查连接,这对于一个稳定的系统很重要.
如果在系统中非必需使用事务的表,可以使用MyISAM的表引擎,对于查询速度来说远远高与InnoDB,或者可以考虑做master-slave的主从架构,读操作在slave中执行,slave中全部使用MyISAM的表引擎,可以加快速度,所有写的操作在master中进行,可以使用InnoDB.
但是如果要做HA,master-slave的架构就不行了,可以考虑采用MySQL Cluster NDB.

2.Jboss

因为是单台Jboss,所以没有使用前端负载,在Jboss主要做2部分优化
(1)Jboss web
web方面Jboss主要还是采用Tomcat做内嵌,首先要并发肯定是先提高工作线程数,tomcat默认的是200,我们的目标是500,所以就分配了550个工作线程,毕竟Servlet处理请求是每来一个请求分配一个工作线程.
在相应时间上,可以使用默认的2000ms,也就是20s,因为指标是平均响应时间,当然不排除一些max与min,max值高的时候是多少谁都不好说.
(2)Jboss ejb
ejb这边我们既使用了stateless,也使用了stateful.
首先要调整的肯定是JVM的内存空间,我们使用的是JBoss5,默认的JVM内存空间为-Xms128m -Xmx512m -XX:MaxPermSize=256m,这里我们只调整xms与xmx,MaxPermSize我调整过,但是并发时会发生异常,具体什么原因我找到后在补上,但是这个参数对性能提高不是很明显,起初我调整了最小JVM内存到1024,最大到3036,最大不要超过服务器内存的3/4,剩下的1/4需要留给操作系统使用。
但是Xms=1024,Xmx=3036这样有个很严重的问题,大家都知道Java有gc机制,但是什么时候gc呢,书上都是说不确定,除非你显示的调用System.gc(),但很少有人会去业务系统里显示的调用gc,在我测试的过程中发现,在系统运行中,Jboss占用的内存一直在往3036m上涨,但到3036m上的时候,系统会突然停顿,因为这时候真正的开始gc了,这个gc线程的优先级很高,其他的线程都要等待它完成才能继续操作,这导致了我的业务瞬时停止了1-2秒左右,如果说在生产系统中,处于高峰期的业务,这样很容易使系统崩溃掉,从网搜寻了相关的解决方法,就是调整Xms与Xms一致,也就是说一开始就给系统分配最大能使用的内存,这样就不会出现系统突然因为jvm的gc出现停顿的问题.
其次由于使用了ejb,需要调整对象缓存池的大小,jboss默认的stateless与stateful都只有20个,远远不够用,我调整到了1000.
还有个需要调整的就是Jboss的连接池,Jboss默认的ds只有15个,远远不够,我将其调整为500,可能有点大,但是做到不缺.
可能还有一些方法可以去掉jboss不用的服务,通过精简jboss结构来做优化,由于以后还要使用集群,所以我没这样去做.

3.Java Code

基本的优化大家都知道,比如这次我发现开发过程中很多人喜欢使用String.format这个方法,用起来确实很爽,按照参数的位置,填充模板字符串就OK了,但在源代码里我发现了new String(...)这样的操作,效率很低,远不如使用StringBuilder与StringBuffer,请大家慎用.
还有个地方,我发现大家在使用ejb的时候很喜欢使用@EJB这样的注解,这个操作也很费时间,尽量把需要复用的ejb stb缓存起来,不然如果在stateful这样的ejb中注入一个stateless ejb, 每当有请求来stateful时,都会让Jboss容器来执行一个通过@EJB查找,然后注入的过程,如果是在Servlet中呢,可以使用http session缓存stateful stb, 或者在init方法里边缓存stateless stb,这样性能会提升很多.

当然程序中最费时的莫属I/O操作了,像日志这样的东西,尽量打印关键的,必要的信息,尽量减少日志的输出,如果非实时日志,可以采用日志缓冲输出.

还要说的一点就是entity bean, 做关联不可怕,可怕的是关联出没必要的数据,非必要的地方还是采用延迟加载,如果有比较大的字段,可以使用属性延迟加载,避免N+1,尽量减少数据库压力.

4.Cache

这里我主要写说下实体的缓存,毕竟操作DB的代价是昂贵的,所以尽量减少与DB的交互,那么就需要使用到对象缓存与查询缓存,定义就不细说了.

最近我主要对JbossCache与memcached做了一下比较.

JbossCache 可以利用本地内存进行缓存,中间不通过TCP/IP,JbossCache又叫做TreeCache,结构跟树一样,节点下边挂子节点,JbossCache大力在做事务,可以保证Cache的准确度不被异常影响,但是在集群方面肯定需要去同步,开销可想而知,但对HA要求高的系统来说是必要的.

Memcached 是一个C/S架构的cache, 它的结构类似一个hashtable,官方放建议使用TCP传输,这样就有TCP网络通信的开销,缺点呢,就是不支持事务,如果程序异常,可能需要自己处理cache的清理工作,但是在分布式方面,大多数memcached分布式架构上都才用hash请求的策略,所以减少的同步的开销.

相比之下,我们采用了JbossCache,将来使用session sticky模式,不去做cache的同步,如果单个节点down掉,负载到其他机器上没有cache,再去数据库中取就可以了,所以没必要做同步.

先写这么多吧,累了,有时间我再补点。:)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值