性能测试中,CPU和内存是关注最多的两个性能指标。以我行应用最多的系统架构(WAS+Oracle)来讲,CPU使用率高的问题多发生于数据库,好比索引不当引起的表扫描、绑定变量使用不当引起的硬解析、链接池使用不当引起的频繁创建断开链接,这些都会致使数据库服务器CPU使用率高。java
内存问题则多发生于应用服务器。部署在WAS平台的Java应用,常常发生的问题是JVM堆内存溢出。产生该问题的缘由有不少:数据库
·由环境引起的,虚拟机物理内存不足;服务器
·由参数配置引起的,JVM堆内存设置太小;session
·由应用程序引起的,内存泄露,错误使用大对象等等。架构
在实际性能测试过程当中选择监控指标时,对JVM堆内存的监控分析比对操做系统内存的分析更为重要。JVM堆内存溢出的缘由中,虚拟机物理内存不足经常被忽视。本文结合项目测试过程当中发现的由内存不足引起的性能问题,设计几个场景来探索JVM堆内存和虚拟机内存之间的影响关系。性能
1、测试
莫名其妙的“会话超时”spa
在某交易(登陆+查询+退出)的疲劳场景中,发现应用服务器内存使用率超过90%,且被测交易存在大量报错:用户未登陆或已超时,请登陆。WAS中会话相关的两个参数,最大内存中会话数1000和会话超时30分钟。性能测试场景中,会话数使用不到1000,且登陆以后并无退出,也不会发生用户未登陆或已超时。因此,报错的缘由在哪里?操作系统
WAS的JVM堆内存和操做系统内存状态如图所示。线程
能够看到,JVM堆内存的分配达到最大值3G,堆实际使用值在到达3G时发生GC,循环如是。JVM堆内存未发生内存溢出,没有生成heapdump、javacore文件,Server没有重启。操做系统内存使用已达92%,且Swap空间使用了1G左右。
Swap分区一般被称为交换分区,这是一块特殊的磁盘空间,当实际内存不够用的时候,操做系统会从内存中取出一部分暂时不用的数据,放在交换分区中,从而为当前运行的程序腾出足够的内存空间。也就是说,当操做系统开始使用Swap空间时,就意味着内存不够。同时,因为Swap分区是磁盘空间,使用Swap分区会频繁读写磁盘,这会显著下降操做系统的运行速度。
根据以上分析,初步判断,虚拟机内存不足,使用到Swap分区。若是session信息被从内存交换到Swap分区,那这段时间该线程的查询请求,没法验证到session,就会报“用户未登陆或已超时,请登陆”,交易失败;若是session信息又被从Swap交换至内存,又不报错,交易成功。下面经过一些实验来验证这一推测。
2、
揭开内存的神秘面纱
首先,咱们看一下测试环境和生产环境的资源配置。能够看出测试环境单台虚拟机的配置(CPU内存)是生产环境的1/2,这也是内存不足的根源,下面围绕内存设计三个场景的测试。
场景一:疲劳测试发生问题的场景。
JVM堆内存GC正常,虚拟机内存不足,使用了Swap分区。为了进一步肯定Swap分区确实是被WAS使用 ,咱们进入到/proc下WAS Server进程的目录,cd /proc/${WasServerPid},该目录下的smaps文件详细记录了该进程的内存使用状况,而后执行cat smaps | grep Swap | grep -v "0 kB" | sort -nr,即可查看进程对Swap的使用。经过查看,该WAS节点的Server1使用了538MB,Server2使用了574MB,加起来1G左右,这与此前监控的结果相符。而重启Server时,这两个值都是0,即未使用Swap分区。
场景二:每一个节点只保留1个Server,JVM堆内存最大值为3G,虚拟机8G内存对于单Server彻底够用。
测试过程当中,交易总体运行平稳,没有报错。JVM堆的分配值也是到达3G,而后经过GC循环使用。但因为只启动了一个Server,内存够用,没有使用到Swap分区,而且存在必定的富余。WAS的JVM堆内存和操做系统内存状态如图所示。