环境:这是一个来自网络的案例:一个数字校园应用系统,运行在一台4个CPU的Solaris 10操作系统上,中间件为ClassFish服务器。系统在进行大并发压力测试的时候,发现请求响应时间比较慢,通过操作系统的mpstat工具发现CPU使用率很高,并且占用
绝大多数CPU资源的程序并不是应用系统本身。这是不正常的现象,通常情况下用户应用的CPU占用率应该占主要地位,才能说明系统是正常工作的。
问题:CPU的占有率很高
分析:通过Solaris 10的Dtrace脚本可以查看当前情况下哪写系统调用话费了最多的CPU资源,Dtrace运行后发现最消耗CPU资源竟然是“fork”系统调用。众所周知,“fork”系统调用是Linux用来产生新进程的,在Java虚拟机中,用户编写的java代码最多只有
线程的概念,不应当有进程产生。
这是个非常异常的现象。通过本系统的开发人员最终找到答案:每个用户请求的处理都需要执行一个外部shell脚本来获得系统的一些信息。执行这个shell脚本是通过java的Runtime.getRuntime().exec()方法来调用的。这种调用方式可以达到目的的,
但是它在Java虚拟机中非常消耗资源,即使外部命令本身能很快执行完毕,频繁调用时创建进程的开销也是非常可观。Java虚拟机执行这个命令过程是:首先克隆一个和当前虚拟机拥有一样环境变量的进程,在用这个新的进程去执行外部命令,最后在退
出这个进程。如果频繁执行这个操作,系统的消耗会过大,不仅是CPU,内部的负担也很重要。
解决:用户根据建议去掉这个shell脚本执行的语句,改为使用Java的API去获取这些信息后,系统很快就恢复正常。