性能测试之性能问题分析

开始性能测试前须要了解的内容:
  一、项目具体需求。
  二、指标:响应时间在多少之内,并发数多少,tps多少,总tps多少,稳定性交易总量多少,事务成功率,交易波动范围,稳定运行时长,资源利用率,测哪些交易,哪些接口,测试哪些场景。
  三、环境:生产环境服务器数量,测试环境服务器数量,按照资源配比得出测试指标。
  四、协议:系统用什么协议进行通信。
  五、压力机数量:若是并发用户数太多,须要把压力发到不一样的压力机,否则可能会存在压力机瓶颈问题,致使tps和响应时间抖动。
  六、交易占比:分析线上日志得出tps占比。
  七、系统架构:请求流通过哪些环节,压测时监控这些环节。
 
   测试策略:
  一、基准:一个用户迭代100次,关注响应时间,事务成功率100%。
  二、负载:10个用户跑10分钟,关注响应时间,事务成功率100%。
  三、容量:估算一个总tps,根据公式计算出每一个交易的pacing和vu,获取系统最大处理能力(最优容量),再令外测出三个梯度做为对比(两组小于最优容量,一组大于最优容量),四组容量VU等差,tps等差,对比每组容量实际占比和测试占比(越接近越能模拟真实场景),关注响应时间,总tps,tps,事务成功率,AP cpu利用率,DB cpu利用率,线程死锁, 数据库死锁。
  其中响应时间应小于负载测试时间,总tps应约等于预估总tps(相差不超过10是正常的),每一个交易的tps应接近预估总tps*占比,事务成功率100%,AP cpu小于60%,DB cpu小于80%。dump线程栈检测是否有线程死锁,查看数据库日志看是否有数据库死锁。
  四、稳定性:采起最优容量的80%做为压力持续运行24小时,观察系统长时间运行的性能表现,关注响应时间,tps,总tps,事务成功率,交易总数,观察是否有内存溢出(堆溢出,栈溢出,持久代溢出),cpu利用率是否达标,mem是否不持续增加,是否能正常触发fullgc,gc时间,gc频率, fullgc时间,fullgc频率(重点关注,JVM调优就是为了减小fullgc频率)。
   
       监控:
  容量测试和稳定性测试时启动nmon监控。
 
压测中遇到的性能问题及解决办法:
1、容量测试过程当中cpu太高
  一、用vmstat实时监控cpu使用状况。很小的压力AP cpu却到了80%多,指标是不能超过60%。
  二、分析是use cpu太高仍是sys cpu太高,常见的是use cpu使用太高。
  三、若是是use cpu使用太高,先把消耗cpu最多的进程找出来(top命令),再找到该线程下消耗cpu太高的是哪几个线程,再把该线程转换成16进制,再用jstack命令来dump线程栈,看这个线程栈在调用什么东西致使use cpu太高。
 
2、内存溢出(堆溢出、栈溢出、持久代溢出)
   一、堆内存溢出
   产生的现象:稳定性压测一段时间后,LR报错,日志报 java.lang.OutOfMemoryError.Java heap space。
      排查手段:
       1)用jmap -histo pid命令dump堆内存使用状况,查看堆内存排名前20个对象,看是否有本身应用程序的方法,从最高的查起,若是有则检查该方法是什么缘由形成堆内存溢出。
  2)若是前20里没有本身的方法,则用jmap -dump来dump堆内存,在用MAT分析dump下来的堆内存,分析导出内存溢出的方法。
   解决方式:若是应用程序的方法没有问题,则须要修改JVM参数,修改xms,xmx,调整堆内存参数,通常是增长堆内存。
   二、栈内存溢出
   产生的缘由:稳定性压测一段时间后,LR报错,日志报Java.Lang.StackOverflowError。
    解决方式:修改jvm参数,将xss参数改大,增长栈内存。
                          栈溢出必定是作批量操做引发的,减小批处理数据量。
   三、持久代溢出
   产生的现象:稳定性压测必定时间后,日志报Java.Lang.OutOfMenoryError.PermGen Space。
        解决方式:
  1)这种缘由是因为类、方法描述、字段描述、常量池、访问修饰符等一些静态变量太多,将持久代占满致使持久代溢出。
  2)修改jvm配置,将XX:MaxPermSize=256参数调大。尽可能减小静态变量。
 
3、线程死锁
   产生的缘由:在多线程程序的编写中,若是不适当的运用同步机制,则有可能形成程序的死锁,常常表现为程序的停顿,或者再也不响应用户的请求。
       产生的现象
  一、容量测试压测一段时间后,LR报链接超时。
  二、形成这种现象的缘由不少,好比带宽不够,中间件线程池不够用,数据库链接池不够,链接数占满等都会形成链接不上而报超时错误。
       排查手段:
  一、jstack命令dump线程栈,搜索线程栈里有没有block,若是有的话就是线程死锁,找到死锁的线程,分析对应的代码。

   jstack -F pid >jts.log(java进程id,能够用jps或者ps aux|grep java 去找),将线程的状态输出到jts.log文件前端

       值得关注的线程状态有:
       死锁,Deadlock(重点关注)
       执行中,Runnable  
       等待资源,Waiting on condition(重点关注)
       等待获取监视器,Waiting on monitor entry(重点关注)
       暂停,Suspended
       对象等待中,Object.wait() 或 TIMED_WAITING
       阻塞,Blocked(重点关注) 
       中止,Parkedjava

       后置处理:把生成的文件,让开发排查几个重点的状态下的业务代码逻辑sql

 

4、数据库死锁
   产生的现象:容量测试压测一段时间后,LR报链接超时。
   排查手段:数据库日志中搜索block,能搜到block的话就是存在数据库死锁,查看对应的sql,优化形成死锁的sql。
 
5、数据库链接池不释放
   产生的现象:容量测试压测一段时间后,LR报链接超时。
   排查与解决方式:去数据库查看应用程序到数据库的链接有多少个( show full processlist),假如应用程序里面配置的数据库链接为30,在数据库查看应用程序到数据库的链接也是30,则表示链接池占满了。将配置改为90试试,去数据库看若是链接到了90,则能够肯定是数据库链接池不释放致使的。查看代码,数据库链接部分是否是有建立链接可是没有关闭链接的状况。基本就是这种状况致使的,修改代码便可。
 
6、TPS上不去
   产生的现象:压力大的时候tps频繁抖动,致使总tps上不去。查看是否有fullgc(tail -f gc_mSrv1.log | grep full)。
        排查手段:
  一、pacing时间间隔设置太大也会致使tps上不去,减少pacing时间间隔。
  二、单压抖动大的交易,发现很平稳,这时怀疑是否是压力太大致使,因此发容量的时候把压力最大的那只交易分到其余压力机,而后发现tps不抖动了。注意:多台压力机只影响tps抖动,不会影响服务器的cpu。
  三、看响应时间有没有超时,看用户数够不够,都在指标内,能够添加用户数。
 
7、服务器压力不均衡(但相差1%-2%是正常的)
  一、跑最优容量的时候,四台APP只有一台cpu超过60%,其余三台都在60%如下。
  二、查看服务器是否有定时任务。
  三、查看是否存在压力机瓶颈。
  四、是否存在带宽瓶颈(局域网不存在此问题)。
  五、查看部署的版本,配置是否同样。
  六、可能别人也在用这些APP,由于同一台物理机上有不少虚拟机,由于别人先用,资源被别人先占了。
       七、前置服务器承担负载调度(Nginx,lvs)分配策略问题
 
8、fullgc时间太长
       产生的缘由及排查手段:
  一、跑容量和稳定性的时候,出现LR报请求超时错误
       二、查看后台日志是fullgc了,看LR几点报的错和日志里fullgc的时间是否对应,fullgc会暂停整个应用程序,致使LR前端没响应,因此报错,这时能够减小old代内存,从而减小fullgc时间,减小fullgc时间LR就不会报错,让用户几乎感受不到应用程序暂停。
   解决方式:四台APP轮流着full gc(部分 server fullgc,其余server也会fullgc),这时能够制定策略让不一样的server不一样时fullgc,或者等夜间交易量少时写定时任务重启服务。
 
9、LR报链接超时
       一、形成这种现象的缘由不少,好比数据库死锁、数据库链接池不释放、fullgc时间太长、堆内存溢出、栈内存溢出、持久代溢出、带宽不够,中间件线程池不够用,数据库链接池不够,链接数占满等都会形成链接不上而报超时错误。
 
   注意:
  服务器日志为error下测试。
  服务启动后几分钟内发压压力会很大,最好是服务启动两三分钟后再开始跑压力。
 
 性能问题分析流程

一、查看服务器的CPU、内存 、负载等状况
二、查看数据库健康状态
三、查看项目日志(查看无特殊现象)
四、查看jvm的gc等状况
五、回滚上一个版本(通常是最后的手段)数据库

相关文章
相关标签/搜索