性能问题的定位分析(四)——大话性能测试(25)

发表于:2022-7-25 09:41

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:胡通    来源:51Testing软件测试网原创

  内存类。内存异常、内存泄漏是最常见的问题。
  例如,使用JMeter对保险公司投保接口进行压力测试,增大压力开始测试后,返回很多错误请求。观察后台接口日志,具体错误如下:
  原因分析如下。
  JVM向操作系统申请创建新的原生线程(nativethread)时,有可能会碰到“java.lang.OutOfMemoryError:Unabletocreatenewnativethread”错误。如果底层操作系统创建新的原生线程失败,JVM就会抛出相应的OutOfMemoryError。总体来说,导致"java.lang.OutOfMemoryError:Unabletocreatenewnativethreadw错误的场景大多经历以下这些阶段。
  (1)Java程序向JVM请求创建一个新的Java线程,JVM本地代码(nativecode)代理该请求,尝试创建一个操作系统级别的原生线程。
  (2)操作系统尝试创建一个新的原生线程,同时需要分配一些内存给该线程。
  (3)如果操作系统的虚拟内存已耗尽,或者是受到32位进程的地址空间限制(2GB-4GB),操作系统就会拒绝本地内存分配。
  (4)JVM抛出java.lang.OutOfMemoryError:Unabletocreatenewnativethreadw错误。
  根据栈信息,我们定位到问题代码出现在下面这个方法里,此方法实现的功能是异步调用保险公司投保接口:
  分析这段代码,开发人员在处理异步任务时,使用了线程池。使用线程池处理多线程的好处有:重用了存在的线程,减少了对象创建、消亡的开销,性能佳;可有效控制最大并发线程数,提高了系统资源的使用率,同时避免了过多资源竞争,避免了堵塞;提供了定时执行、定期执行、单线程和并发数控制等功能。
  问题就出现在"ExecutorServicees=Executors.newFixedThreadPool(l);"这一行代码上。newFixedThreadPool方法的功能是创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。开发人员在此处创建线程池时使用了局部变量,每个请求进入这个方法时,都会新建一个固定线程个数为1的线程池。就这样大量并发请求进入后,新建了大量的线程,导致系统虚拟内存被耗尽,JVM抛出ajava.lang.OutOfMemoryError:Unabletocreatenewnativethreadw错误。
  配置类。很多时候各个中间件本身的参数是不能满足业务的性能需求的,需要根据实际用户量灵活地调整。例如,数据库连接池不够用导致响应时间久。
  问题现象:在测试一个场景时,我们发现响应时间很长,但日志无报错现象。根据调用链接逐级定位,我们发现80%的时间都是消耗在数据访问对象(DataAccessObject,DAO)层的方法上,这时首先考虑的是SQL会不会有问题?于是找数据库管理员(DatabaseAdministrator,DBA)帮忙抓取SQL看一下,但DBA反映SQL执行很快,执行计划也没有问题,那问题出现在哪里呢?找不到原因就看一下线程栈,我们看看系统在执行DAO层的方法后做了什么ojstack线程栈如下:
  问题分析过程如下。
  我们先关注线程状态,发现栈信息里大量的Dubbo线程处于TTMED—WAITING状态。从waitingoncondition可以看出系统在等待一个条件发生,这时的线程处于休眠(sleep)状态。一般系统会有超时时间唤醒,这里出现TIMED_WAITING状态很正常,一些等待10都会出现这种状态,但是出现大量的TIMED_WAITING状态就要找原因了。接下来,我们观察线程栈,发现处于TIMED_WAITING状态的线程都在等待Druid获取连接池的连接,这种现象很像连接池不够用了。于是增加数据库连接池的连接数,然后TPS直接提升了3倍。
  最后再做一下简要总结分析CPU占用和内存性能的方法和手段。
  (1)分析CPU占用的方法和手段如下。
  top命令用于査看实时的CPU使用情况。
  ps-ef命令用于査看进程以及进程中线程的当前CPU使用情况,以及属于当前状态的釆样数据。
  jstack是Java提供的命令,用于査看某个进程的当前线程栈运行情况。根据这个命令的输出可以定位某个进程的所有线程的当前运行状态、运行代码,以及是否死锁等。
  pstack是Linux命令,用于査看某个进程的当前线程栈运行情况。
  (2)分析内存性能的方法和手段如下。
  top命令用于査看实时的内存使用情况。
  执行jmap-histo:live[pid],然后分析具体的对象数目和占用内存大小,从而定位代码。
  执行jmap-dump:live,foimat=b,file=xxx.xxx[pid],然后利用MAT分析是否存在内存泄漏等问题。
  另外,典型的影响性能的问题有以下几个。
  系统对高并发的场景响应不足,如数据库连接池的连接数过低、服务器连接数超过上限、数据库锁控制考虑不足等。
  内存泄漏,如在长时间运行下内存没有正常释放,发生宕机等。
  数据库优化不足,如业务日益增长、关联表众多、SQL不够优化等。
  更多日常性能测试遇到的典型问题如表1-6所示。
  表1-6日常性能测试遇到的典型问题
查看《大话性能测试》全部连载章节
版权声明:51Testing软件测试网获得作者授权连载本书部分章节。
任何个人或单位未获得明确的书面许可,不得对本文内容复制、转载或进行镜像,否则将追究法律责任
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号