tune app performance
- 为什么要写这篇文章,是因为最近线上product出现的性能问题因为上次的发布而引起巨大的波动,cpu使用率从日常的20%左右一下飚升到了最高能达到80%,load值从平常的2左右飚升到10,这个数字我想不管是对于开发、dba、sa来说如果碰到这样的事情,我想心情至少下降好几个等级,这意味着产品存在很严重的问题,那必然接下是花时间去解决掉问题,但是因为这次的发布全是因为webapp所致,于是最紧迫的工作就是赶快抓紧时间去分析解决问题的思路和方法.我先对这个系统做一个大概的概述,首先主站会发出一个searchrequest,到后端以后会组装成wrapperlist,然后通过AMQ通道来发送消息到另一个系统(在该系统先会去cache取数,如果每有会触发wrapper上各个站点去抓数据),而可想而知其实最为主要的还是公司内部系统,也就是wrapper会定时去抓取这些数据放到cache中,也是一个庞大的数据量的系统,而且公司内部这个系统还会于第三方数据进行交互,所以整个系统架构还是比较复杂,于是在性能评估的时候没有很好的办法,因为于第三方去交互的时候属于跨网络交互(当然在这一层也有cache机制,服务器数量大概是20台tomcat,30台memcache,其它系统具体数量不便公开),于是一个问题是很多时候跟第三方打交道时候也会消耗更更多的资源在网络I/O上(当然如果searchrequest在cache中hit的话就不会于第三方交互,只是自己的服务器局域网会有一个I/O上的消耗)..
既然问题出现了,首先就只能从app去优化系统,于是先是代码方面的调整,在这个层面来说无非就是尽量频繁去创建一些不必要的object,以避免JVM不断的去做GC工作,然后就是调整一下heap的内存大小(包括old区,edge区,永久区),这些调整只是能保证一个健康系统内存是足够的,但是并能解决所有的问题,这次产品的发布以后是cpu的us%比飚高,于是可以肯定的是因为程序导致的,因为如果是系统线程或系统本身的问题话,cpu的sy%这个值也会跟着飚高,但是这个值一值是一个很平稳的值,基本没有任何变化..于是果断判断不是系统带来的问题...于是使用jstack导出线上环境的栈信息进行分析,结果能看到很多waitingonmonitor等等这样的信息,于是判断cpu在频繁的做运算,于是出于这个问题,对代码中不必要的运算做处理(主要还是forloop,尤其是涉及到数量级别的数据时,切忌这一点正确处理好forloop),还有一点就是一定要保证edge区不要使系统不断的去做gc.,不断的去gc也是一个导致系统不稳定的点...在这个过程中经历层层分析和调试以后性能相对来说降到了基本和发布之前的状态...
下面简单谈谈一个系统如果出现问题应该分析点:首先对于开发来说目前架构基本上是保持三层架构,前端是一些server(nginx,lighttpd,apache等等),这些server主要是用来处理一些静态文件,然后就是负责loadbalance,转发到下层的时候才是我们的app部分,对于最后一个层结构来说我想也不必多说,那就是db,是任何一个机构的核心。app部分只是一些指令而已,但最终的处理还是在数据,我在此也主要是想简单谈谈app这一层。对于app这一层来说也就大概以下几个点比较重要:I/O、Memory、CPU,(当然如果你的系统涉及就到跨域问题那当然还存在网络I/O)。
对于I/O部分来说无非就是写入、读出操作(如果app涉及到网络数据交互还存在网络I/O),对于这类操作我们没有办法去控制,只是避免不必要的频繁的I/O操作,来达到系统稳定的目的,像Linux服务器下可以使用iostat,sar这些命令来分析,在windows同样可以找一些工具来分析,或者直接用windowstaskmgr来分析。
Memory这我想对于任何一个系统来说这是一个指标,很多系统默认情况下会在硬盘区开辟一段vmmemory来避免内存不足的问题(这个值当然也是我们必须设置的一个值,除非有一种情况能保证物理内存是足够用的,可以不用调整该参数,该参数一般是物理内存的1.5倍到2倍,是一个经验值),因为内存是按页来存储的,所以还有一个问题就是避免跨page获取数据,跨page操作是很消耗性能的一个工作。对于JVM内存分配我想应该根据app应用而调整。对于内存来说可以使用vmstat,top命令来分析,当swap使用足够多的时候就要考虑是什么原因导致的。
最后一个我想也是核心,那就是CPU,它是执行指令的指挥手,任何一个返回的数据多是基于它的指令返回的,当然首先一点的是对于app来说只是涉及到运算问题,尤其是程序涉及到多层循环的时候是很消耗cpu的(尤其涉及到大数据量处理),在此就是避免不必要的循环操作以及避免JVM做不必要的对象创建工作,这次系统的负载飚升就是因为运算量过大的问题,当然对于程序部分也进行过性能优化。最终来说还是达到了一个比较理想的效果。对于cpu来说我们可以大概使用以下手段来分析:top、sar这些命令,top命令执行以后可以使用shift+p来按进程使用cpu大小来排序分析,或者直接M可以看到每一个进程使用memory情况..
总之,对于apptuning来说没有更好的办法,只能一步一步分析,这是唯一的办法,然后就是靠自己的平时的积累和经验。最好的办法我想是从写app开始的第一步开始,做好每一个步骤。避免一些问题的出现..